3188: [Coci 2011]Upit
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 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
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的下传顺序了。
代码:
View Code
问题主要在操作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 ",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 }