【金色】种瓜得瓜,种豆得豆 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 }

 

上一篇:Ubuntu16.04下Intellij IDEA不能输入中文的问题


下一篇:C - Portals Gym - 102006C (网络流最小割)