hdu5828 Rikka with Sequence(线段树)

来源:互联网 发布:建立数据系统技术 编辑:程序博客网 时间:2024/06/13 21:47

思路:HDU4027的升级版,多了一个区间add的操作,考虑一下显然开根号的递减速度是很快的,2^64最多不超过8次就能减到1,而且会出现很多区间的数字都是一样的情况,那么可以在线段树多维护一个flag值,表示区间里面是否所有数都是相等的,如果是的话那么开根号就只开到这里就行了,具体实现细节还是蛮多的....


后来HDU加数据了,比如2 3 2 3 2 3然后整体加6然后开根号,又会变回2 3 2 3 2 3相当于不会出现区间数字一样的情况了,这样就相当于没剪枝,变成了n^2...后来发现只有极差为1的时候才会出现这种情况,极差>1的话是不可能维持原来的序列的,那么就可以维护一个最大值和最小值,如果极差为1的话那么区间开根号其实相当于区间减去了x-sqrt(x),再加上第一个版本的剪枝就可以2000MS左右过去了

第一版本(TLE):

#include<bits/stdc++.h>using namespace std;const int maxn = 100000+50;#define LL long long#define eps 1e-8#define LL long long#define lson i<<1,l,mid#define rson i<<1|1,mid+1,rLL sum[maxn<<2],lazy[maxn<<2],flag[maxn<<2];void push_up(int i){    sum[i]=sum[i<<1]+sum[i<<1|1];if(flag[i<<1]==flag[i<<1|1])flag[i]=flag[i<<1];elseflag[i]=0;}void pushdown(int r,int m){     if(flag[r]) { flag[r<<1]=flag[r]; flag[r<<1|1]=flag[r]; sum[r<<1]=flag[r]*(m-m/2); sum[r<<1|1]=flag[r]*(m/2); lazy[r]=0; } if(lazy[r]) { lazy[r<<1]+=lazy[r]; lazy[r<<1|1]+=lazy[r]; if(flag[r<<1]) flag[r<<1]+=lazy[r]; if(flag[r<<1|1]) flag[r<<1|1]+=lazy[r]; sum[r<<1]+=lazy[r]*(m-m/2); sum[r<<1|1]+=lazy[r]*(m/2); lazy[r]=0; }}void build(int i,int l,int r){     lazy[i]=0; flag[i]=0; if(l==r) { scanf("%d",&sum[i]); flag[i]=sum[i]; return; } int mid = (l+r)>>1; build(lson); build(rson); push_up(i);}void update(int ql,int qr,int v,int i,int l,int r){     if(ql<=l && qr>=r) { sum[i]+=1LL*(r-l+1)*v; lazy[i]+=v; if(flag[i]) flag[i]+=v; return; } pushdown(i,r-l+1); int mid = (l+r)>>1; if(ql<=mid) update(ql,qr,v,lson); if(qr>mid) update(ql,qr,v,rson); push_up(i);}void update1(int ql,int qr,int i,int l,int r){     if(ql<=l && qr>=r && flag[i]) { flag[i]=(sqrt(flag[i])+eps); sum[i]=1LL*flag[i]*(r-l+1); return; } pushdown(i,r-l+1); int mid = (l+r)>>1; if(ql<=mid) update1(ql,qr,lson); if(qr>mid) update1(ql,qr,rson); push_up(i);}LL query(int ql,int qr,int i,int l,int r){    if(ql<=l && qr>=r)return sum[i];pushdown(i,r-l+1);int mid = (l+r)>>1;LL ans = 0;if(ql<=mid)ans+=query(ql,qr,lson);if(mid<qr)ans+=query(ql,qr,rson);return ans;}int main(){    int T;scanf("%d",&T);while(T--){int n,q;scanf("%d%d",&n,&q);build(1,1,n);while(q--){int x,y,w,op;scanf("%d",&op);if(op==1){scanf("%d%d%d",&x,&y,&w);update(x,y,w,1,1,n);}if(op==2){scanf("%d%d",&x,&y);update1(x,y,1,1,n);}if(op==3){scanf("%d%d",&x,&y);printf("%lld\n",query(x,y,1,1,n));}}}}


更新版:

#include<bits/stdc++.h>using namespace std;const int maxn = 100000+50;#define LL long long#define eps 1e-8#define LL long long#define lson i<<1,l,mid#define rson i<<1|1,mid+1,rLL sum[maxn<<2],lazy[maxn<<2],maxx[maxn<<2],minn[maxn<<2];const int read(){char ch = getchar();while (ch<'0' || ch>'9') ch = getchar();int x = ch - '0';while ((ch = getchar()) >= '0'&&ch <= '9') x = x * 10 + ch - '0';return x;}void push_up(int i){maxx[i]=max(maxx[i<<1],maxx[i<<1|1]);minn[i]=min(minn[i<<1],minn[i<<1|1]);    sum[i]=sum[i<<1]+sum[i<<1|1];}void pushdown(int r,int m){ if(lazy[r]) { lazy[r<<1]+=lazy[r]; maxx[r<<1]+=lazy[r]; maxx[r<<1|1]+=lazy[r]; minn[r<<1]+=lazy[r]; minn[r<<1|1]+=lazy[r]; lazy[r<<1|1]+=lazy[r]; sum[r<<1]+=lazy[r]*(m-m/2); sum[r<<1|1]+=lazy[r]*(m/2); lazy[r]=0; }          if(minn[r]==maxx[r]) { minn[r<<1]=maxx[r<<1]=minn[r<<1|1]=maxx[r<<1|1]=minn[r]; sum[r<<1]=minn[r]*(m-m/2); sum[r<<1|1]=maxx[r]*(m/2); }}void build(int i,int l,int r){     lazy[i]=0; if(l==r) { scanf("%d",&sum[i]); minn[i]=sum[i]; maxx[i]=sum[i]; return; } int mid = (l+r)>>1; build(lson); build(rson); push_up(i);}void update(int ql,int qr,int v,int i,int l,int r){     if(ql<=l && qr>=r) { minn[i]+=v; maxx[i]+=v; sum[i]+=1LL*(r-l+1)*v; lazy[i]+=v; return; } pushdown(i,r-l+1); int mid = (l+r)>>1; if(ql<=mid) update(ql,qr,v,lson); if(qr>mid) update(ql,qr,v,rson); push_up(i);}void update1(int ql,int qr,int i,int l,int r){     if(ql<=l && qr>=r) { if((int)sqrt(minn[i]) == (int)sqrt(maxx[i])) { minn[i]=maxx[i]=(int)sqrt(minn[i]); sum[i]=minn[i]*(r-l+1); } else if(minn[i]+1==maxx[i]) { int k = maxx[i]-(int)sqrt(maxx[i]); update(ql,qr,-k,i,l,r); } else {         pushdown(i,r-l+1); int mid = (l+r)>>1; if(ql<=mid)update1(ql,qr,lson); if(qr>mid)update1(ql,qr,rson); push_up(i); } return; } pushdown(i,r-l+1); int mid = (l+r)>>1; if(ql<=mid) update1(ql,qr,lson); if(qr>mid) update1(ql,qr,rson); push_up(i);}LL query(int ql,int qr,int i,int l,int r){    if(ql<=l && qr>=r)return sum[i];pushdown(i,r-l+1);int mid = (l+r)>>1;LL ans = 0;if(ql<=mid)ans+=query(ql,qr,lson);if(mid<qr)ans+=query(ql,qr,rson);return ans;}int main(){    int T;scanf("%d",&T);while(T--){int n,q;scanf("%d%d",&n,&q);//n = Scan();//q = Scan();build(1,1,n);while(q--){int x,y,w,op;scanf("%d",&op);if(op==1){scanf("%d%d%d",&x,&y,&w);//x = Scan();//y = Scan();//w = Scan();update(x,y,w,1,1,n);}if(op==2){scanf("%d%d",&x,&y);//x = Scan();//y = Scan();update1(x,y,1,1,n);}if(op==3){scanf("%d%d",&x,&y);//x = Scan();//y = Scan();printf("%lld\n",query(x,y,1,1,n));}}}}


Problem Description
As we know, Rikka is poor at math. Yuta is worrying about this situation, so he gives Rikka some math tasks to practice. There is one of them:

Yuta has an array A with n numbers. Then he makes m operations on it. 

There are three type of operations:

1 l r x : For each i in [l,r], change A[i] to A[i]+x
2 l r : For each i in [l,r], change A[i] to A[i]
3 l r : Yuta wants Rikka to sum up A[i] for all i in [l,r]

It is too difficult for Rikka. Can you help her?
 

Input
The first line contains a number t(1<=t<=100), the number of the testcases. And there are no more than 5 testcases with n>1000.

For each testcase, the first line contains two numbers n,m(1<=n,m<=100000). The second line contains n numbers A[1]~A[n]. Then m lines follow, each line describe an operation.

It is guaranteed that 1<=A[i],x<=100000.
 

Output
For each operation of type 3, print a lines contains one number -- the answer of the query.
 

Sample Input
15 51 2 3 4 51 3 5 22 1 43 2 42 3 53 1 5
 

Sample Output
56
 

Author
学军中学
 

0 0
原创粉丝点击