【金色】种瓜得瓜,种豆得豆 Gym - 102072H (线段树)
题目链接:https://cn.vjudge.net/problem/Gym-102072H
题目大意:中文题目
具体思路:通过两棵线段树来维护,第一棵线段树来维护当前坐标的点的日增长速度(默认每一年的增长速度都是当前年份的增长速度),对于第一棵线段树,肯定会存在多算的情况,那么我们第二棵线段树就维护每一个点的多算的情况就可以了。
举个例子:当前的n只有1,初始值也是1, 三个操作,第一年加一个,第二年加一个,第三年加一个。然后问你第四年的当前的个数。在第二年的时候增长速度还是1,第三年的增加速度就是2,第四年的增长速度就是3。对于第四年的话,第一棵线段树的结果出来的是3,在乘上年份就是3*4=12,这个12指的是四年的产量按照每一年的增长速度都是3计算的,然后我们通过第二棵线段树减去不合法的情况,分别是第二年和第三年多算了,我们再通过12-3-2就能解出正确的答案了。
感谢qyn的讲解。
AC代码:
1 #include<iostream> 2 #include<stack> 3 #include<stdio.h> 4 #include<cmath> 5 #include<algorithm> 6 using namespace std; 7 # define ll long long 8 # define lson l,m,rt<<1 9 # define rson m+1,r, rt<<1|1 10 const int maxn = 2e5+1000; 11 ll tree1[maxn<<2],tree2[maxn<<2]; 12 ll lazy1[maxn<<2],lazy2[maxn<<2]; 13 ll sto[maxn]; 14 void up(ll rt) 15 { 16 tree1[rt]=tree1[rt<<1]+tree1[rt<<1|1]; 17 tree2[rt]=tree2[rt<<1]+tree2[rt<<1|1]; 18 } 19 void buildtree(ll l,ll r,ll rt) 20 { 21 tree1[rt]=tree2[rt]=0; 22 lazy1[rt]=lazy2[rt]=0; 23 if(l==r) 24 { 25 scanf("%lld",&tree1[rt]); 26 return ; 27 } 28 ll m=(l+r)>>1; 29 buildtree(lson); 30 buildtree(rson); 31 up(rt); 32 } 33 void down(ll rt,ll l,ll r) 34 { 35 ll mid=(l+r)>>1; 36 lazy1[rt<<1]+=lazy1[rt]; 37 lazy1[rt<<1|1]+=lazy1[rt]; 38 tree1[rt<<1]+=lazy1[rt]*(mid-l+1); 39 tree1[rt<<1|1]+=lazy1[rt]*(r-mid); 40 lazy1[rt]=0; 41 lazy2[rt<<1]+=lazy2[rt]; 42 lazy2[rt<<1|1]+=lazy2[rt]; 43 44 tree2[rt<<1]+=lazy2[rt]*(mid-l+1); 45 tree2[rt<<1|1]+=lazy2[rt]*(r-mid); 46 lazy2[rt]=0; 47 } 48 void update(ll l,ll r,ll rt,ll L,ll R,ll year) 49 { 50 if(L<=l&&R>=r) 51 { 52 tree1[rt]+=(r-l+1); 53 lazy1[rt]+=1; 54 tree2[rt]+=(r-l+1)*year; 55 lazy2[rt]+=year; 56 return ; 57 } 58 down(rt,l,r); 59 ll m=(l+r)>>1; 60 if(L<=m) 61 update(lson,L,R,year); 62 if(R>m) 63 update(rson,L,R,year); 64 up(rt); 65 } 66 ll query(ll l,ll r,ll rt,ll L,ll R,ll year) 67 { 68 if(R<l||L>r) 69 return 0; 70 if(L<=l&&R>=r) 71 { 72 return tree1[rt]*year-tree2[rt]; 73 } 74 down(rt,l,r); 75 ll m=(l+r)>>1; 76 return query(lson,L,R,year)+query(rson,L,R,year); 77 up(rt); 78 } 79 int main() 80 { 81 //freopen("data1.out","r",stdin); 82 ll n; 83 while(~scanf("%lld",&n)) 84 { 85 buildtree(1,n,1); 86 ll year=0; 87 int m; 88 char str[10]; 89 ll st,ed,num=0; 90 scanf("%d",&m); 91 while(m--) 92 { 93 scanf("%s %lld %lld",str,&st,&ed); 94 year++; 95 if(str[0]=='Q') 96 { 97 ll ans=query(1,n,1,st,ed,year); 98 sto[++num]=ans; 99 } 100 else 101 { 102 update(1,n,1,st,ed,year); 103 } 104 } 105 for(int i=1; i<=num; i++) 106 { 107 if(i==1) 108 printf("%lld",sto[i]); 109 else 110 printf(" %lld",sto[i]); 111 } 112 printf("\n"); 113 } 114 return 0; 115 }