当前位置: 代码迷 >> 综合 >> HDU 6315 Naive Operations【线段树+思维】
  详细解决方案

HDU 6315 Naive Operations【线段树+思维】

热度:43   发布时间:2024-01-15 06:53:45.0

传送门
题面:
Naive Operations
Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 502768/502768 K (Java/Others)
Total Submission(s): 650    Accepted Submission(s): 239

Problem Description

In a galaxy far, far away, there are two integer sequence a and b of length n.
b is a static permutation of 1 to n. Initially a is filled with zeroes.
There are two kind of operations:
1. add l r: add one for al,al+1...ar
2. query l r: query ∑ri=l?ai/bi?

Input

There are multiple test cases, please read till the end of input file.
For each test case, in the first line, two integers n,q, representing the length of a,b and the number of queries.
In the second line, n integers separated by spaces, representing permutation b.
In the following q lines, each line is either in the form 'add l r' or 'query l r', representing an operation.
1≤n,q≤100000, 1≤l≤r≤n, there're no more than 5 test cases.

Output

Output the answer for each 'query', each one line.

Sample Input

5 12 1 5 2 4 3 add 1 4 query 1 4 add 2 5 query 2 5 add 3 5 query 1 5 add 2 4 query 1 4 add 2 5 query 2 5 add 2 2 query 1 5

Sample Output

1 1 2 4 4 6

题意:
  给你一个数组a[i]和b[i],其中a[i]最开始为0,b[i]为n的任意排列。

 有两种操作,第一种在区间[l,r]中将a[i]加1。第二种统计区间[l,r]的 ai/bi(下取整)的和。
分析:

算法肯定是线段树,我们观察a[i]/b[i](下取整)什么时候才能+1,a[i]在区间更新的时候+1到b[i],加到n*b[i]就有n个1,这时候我们可以用sum++记录加1的个数,我们可以维护a的最大值maxa和b的最小值minb。

在区间更新的时候,如果maxa<minb,没有必要向下更新

f否则一直更新到所需要的,到达后,sum++,minnb+=b[l](为下一次+1更新值)

 

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <math.h>
#include <bitset>
#include <algorithm>
#include <climits>
using namespace std;#define lson i<<1
#define rson i<<1|1
#define LS l,mid,lson
#define RS mid+1,r,rson
#define ll long long
#define N 100005
#define MOD 1000000007
#define INF 0x3f3f3f3f
#define EXP 1e-8
#define lowbit(x) (x&-x)ll b[N];
ll ans_sum,ans_max,ans_min;
struct node
{int l,r;ll sum,maxa,minb;ll add;
} a[N<<2];void pushdown(int i)//标记下传
{if(a[i].add!=0){a[lson].add+=a[i].add;///给左子节点打上延迟标记a[rson].add+=a[i].add;///给右子节点打上延迟标记a[lson].maxa+=a[i].add;a[rson].maxa+=a[i].add;a[i].add = 0;  ///清除标记}}void pushup(int i)
{a[i].sum=a[lson].sum+a[rson].sum;a[i].maxa=max(a[lson].maxa,a[rson].maxa);a[i].minb=min(a[lson].minb,a[rson].minb);
}
//建立线段树 
void build(int l,int r,int i)
{a[i].l = l;a[i].r = r;a[i].add = 0;if(l == r)     {a[i].sum = 0;a[i].maxa = 0;a[i].minb= b[l];return;}int mid = (l+r)>>1;build(LS);build(RS);pushup(i);
}
//a[l,r]+=val 
void add_data(int l,int r,int i,ll val)
{if(a[i].l>=l&&a[i].r<=r){a[i].maxa+=val;if(a[i].maxa<a[i].minb){a[i].add+=val;return;}if(a[i].l==a[i].r&&a[i].maxa>=a[i].minb){a[i].sum++;a[i].minb+=b[a[i].l];return;}}pushdown(i);//标记下传int mid = (a[i].l+a[i].r)>>1;if(l<=mid) add_data(l,r,lson,val);if(r>mid) add_data(l,r,rson,val);pushup(i);
}void query(int l,int r,int i)
{//cout<<l<<" "<<r<<" "<<i<<endl;if(l <= a[i].l && a[i].r <= r){ans_sum += a[i].sum;return ;}pushdown(i);int mid = (a[i].l+a[i].r)>>1;if(l<=mid) query(l,r,lson);if(r>mid) query(l,r,rson);pushup(i);
}int main()
{int n,m;while(scanf("%d%d",&n,&m)!=-1){for (int i=1;i<=n;i++){scanf("%lld",&b[i]);}build(1,n,1);    char ch[2];while(m--){int l, r;scanf("%s", ch);if(ch[0] == 'a'){int x,y;ll v;scanf("%d %d", &x,&y);add_data(x,y,1,1);}else{scanf("%d %d", &l,&r);//cout<<l<<" "<<r<<endl;ans_sum=0;query(l,r,1);printf("%lld\n",ans_sum);}}}return 0;
}

 

  相关解决方案