BZOJ3188: [Coci 2011]Upit

3188: [Coci 2011]Upit

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 72  Solved: 24
[Submit][Status]

Description

你需要维护一个序列,支持以下4种操作。一,将区间(u,v)的数覆盖为C;二,
将区间(u,v)的数依次加上一个以C为首项、C为公差的等差数列;三,将数C插入
第i个位置;四,查询区间(u,v)的数的和。序列最初有n个数,一共会有Q次操
作。保证结果在longlong范围内。 
 
 

Input

Output

Sample Input

5 5
1 2 3 4 5
1 5 5 0
4 4 5
4 5 5
2 1 5 1
4 1 5

Sample Output


4
0
25

HINT

n, Q <= 100,000. 

Source

 

题解:
问题主要在操作2
如果我们给l-r加上一个以x为首项,y为公差的等差数列,v[k]和sum[k]都很容易计算。
我们发现两次的操作是可以合并的  加上以x1为首项,y1为公差,再加上x2为首项,y2为公差,相当于加上了一个以x1+x2为首项,以y1+y2为公差的等差数列,这样我们就可以打lazy了!
然后剩下的就是注意两个lazy的下传顺序了。
代码:
  1 #include<cstdio>
  2 
  3 #include<cstdlib>
  4 
  5 #include<cmath>
  6 
  7 #include<cstring>
  8 
  9 #include<algorithm>
 10 
 11 #include<iostream>
 12 
 13 #include<vector>
 14 
 15 #include<map>
 16 
 17 #include<set>
 18 
 19 #include<queue>
 20 
 21 #include<string>
 22 
 23 #define inf 1000000000
 24 
 25 #define maxn 500000+5
 26 
 27 #define maxm 500+100
 28 
 29 #define eps 1e-10
 30 
 31 #define ll long long
 32 
 33 #define pa pair<int,int>
 34 
 35 #define for0(i,n) for(int i=0;i<=(n);i++)
 36 
 37 #define for1(i,n) for(int i=1;i<=(n);i++)
 38 
 39 #define for2(i,x,y) for(int i=(x);i<=(y);i++)
 40 
 41 #define for3(i,x,y) for(int i=(x);i>=(y);i--)
 42 
 43 #define mod 1000000007
 44 
 45 using namespace std;
 46 
 47 inline ll read()
 48 
 49 {
 50 
 51     ll x=0,f=1;char ch=getchar();
 52 
 53     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 54 
 55     while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();}
 56 
 57     return x*f;
 58 
 59 }
 60 int n,q,rt,t1,t2,tot,fa[maxn],c[maxn][2];
 61 ll s[maxn],sum[maxn],v[maxn],tag[maxn][4];
 62 inline void pushup(int x)
 63 {
 64     int l=c[x][0],r=c[x][1];
 65     s[x]=s[l]+s[r]+1;
 66     sum[x]=sum[l]+sum[r]+v[x];
 67 }
 68 inline void rotate(int x,int &k)
 69 {
 70     int y=fa[x],z=fa[y],l=c[y][1]==x,r=l^1;
 71     if(y!=k)c[z][c[z][1]==y]=x;else k=x;
 72     fa[x]=z;fa[y]=x;fa[c[x][r]]=y;
 73     c[y][l]=c[x][r];c[x][r]=y;
 74     pushup(y);pushup(x);
 75 }
 76 inline void splay(int x,int &k)
 77 {
 78     while(x!=k)
 79     {
 80         int y=fa[x],z=fa[y];
 81         if(y!=k)
 82         {
 83             if(c[z][0]==y^c[y][0]==x)rotate(x,k);else rotate(y,k);
 84         }
 85         rotate(x,k);
 86     }
 87 }
 88 inline void change(int x,ll z)
 89 {
 90     sum[x]=s[x]*z;v[x]=z;
 91     tag[x][0]=1;tag[x][1]=z;
 92     tag[x][2]=tag[x][3]=0;
 93 }
 94 inline void update(int x,ll y,ll z)
 95 {
 96     int l=c[x][0],r=c[x][1];
 97     v[x]+=y+s[l]*z;
 98     sum[x]+=s[x]*y+s[x]*(s[x]-1)/(ll)2*z;
 99     tag[x][2]+=y;tag[x][3]+=z;
100 }
101 inline void pushdown(int x)
102 {
103     int l=c[x][0],r=c[x][1];
104     if(tag[x][0]){change(l,tag[x][1]);change(r,tag[x][1]);tag[x][0]=0;}
105     if(tag[x][2]||tag[x][3])
106     {
107         update(l,tag[x][2],tag[x][3]);
108         update(r,tag[x][2]+(s[l]+1)*tag[x][3],tag[x][3]);
109         tag[x][2]=tag[x][3]=0;
110     }
111 }
112 inline int find(int x,int k)
113 {
114     pushdown(x);
115     int l=c[x][0],r=c[x][1];
116     if(s[l]+1==k)return x;
117     else if(s[l]>=k)return find(l,k);
118     else return find(r,k-s[l]-1);
119 }
120 inline void split(int l,int r)
121 {
122     t1=find(rt,l);t2=find(rt,r);
123     splay(t1,rt);splay(t2,c[t1][1]);
124 }
125 inline void build(int l,int r,int f)
126 {
127     if(l>r)return;
128     int x=(l+r)>>1;
129     fa[x]=f;c[f][x>f]=x;
130     if(l==r){s[x]=1;sum[x]=v[x];return;}
131     build(l,x-1,x);build(x+1,r,x);
132     pushup(x);
133 }
134 
135 int main()
136 
137 {
138 
139     freopen("input.txt","r",stdin);
140 
141     freopen("output.txt","w",stdout);
142 
143     n=read();q=read();
144     for2(i,2,n+1)v[i]=read();tot=n+2;rt=(1+n+2)>>1;
145     build(1,n+2,0);
146     while(q--)
147     {
148         int ch=read();
149         if(ch==3){int x=read();split(x,x+1);fa[c[t2][0]=++tot]=t2;sum[tot]=v[tot]=read();s[tot]=1;}
150         else
151         {
152             int x=read(),y=read();
153             split(x,y+2);
154             if(ch==1)change(c[t2][0],read());
155             else if(ch==4)printf("%lld\n",sum[c[t2][0]]);
156             else 
157             {
158                 ll z=read();update(c[t2][0],z,z);
159             }    
160         }
161         pushup(t2);pushup(t1);
162     }
163 
164     return 0;
165 
166 } 
View Code

 

posted @ 2014-12-02 10:52  ZYF-ZYF  Views(413)  Comments(0Edit  收藏  举报