【COGS 2633】數列操作e
阿新 • • 發佈:2018-12-17
【題目】
題目描述:
一個長度為 的序列,一開始序列數的權值都是 ,有 次操作
支援兩種操作:
- ,給區間 [ , ] 內,第一個數加 ,第二個數加 ,第三個數加 第 個數加
- 查詢區間 [ , ] 內的權值和
每次詢問的答案對 取模
輸入格式:
第一行兩個數 ,,表示序列長度和操作次數
接下來 行,每行描述一個操作,有如下兩種情況:
- ,給區間 [ , ] 內,第一個數加 ,第二個數加 ,第三個數加 …第 個數加
- 查詢區間 [ , ] 內的權值和
輸出格式:
為了減少輸出,你只需要輸出所有答案對 取膜之後的異或和。
樣例資料:
輸入
5 5
1 3 4 1
2 1 5
2 2 2
1 3 3 1
1 2 4 1
輸出
5
提示:
對於 的資料,
對於 的資料,
對於 的資料,,,
【分析】
這道題可以看做是區間加一個二次函式,比較容易可以想到用線段樹做
對於一個 的詢問,() 位置加上的值為 ,看起來不太好求區間和,怎麼辦呢?
實際上把式子拆開,可以得到 ,那麼用三個陣列分別維護 ,,,然後預處理出 和 的字首和就可以快速合併了,下傳也比較容易
然後看到對 取模就直接用 就行了
【程式碼】
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 100005
#define ull unsigned long long
using namespace std;
int n,m,L,R;
ull S[N][2],sum[N<<2][3],add[N<<2][3];
void Pushup(int root)
{
sum[root][0]=sum[root<<1][0]+sum[root<<1|1][0];
sum[root][1]=sum[root<<1][1]+sum[root<<1|1][1];
sum[root][2]=sum[root<<1][2]+sum[root<<1|1][2];
}
void Pushnow(int root,int l,int r,ull w1,ull w2,ull w3)
{
sum[root][0]+=w1*(r-l+1);
sum[root][1]+=w2*(S[r][0]-S[l-1][0]);
sum[root][2]+=w3*(S[r][1]-S[l-1][1]);
add[root][0]+=w1,add[root][1]+=w2,add[root][2]+=w3;
}
void Pushdown(int root,int l,int r,int mid)
{
Pushnow(root<<1,l,mid,add[root][0],add[root][1],add[root][2]);
Pushnow(root<<1|1,mid+1,r,add[root][0],add[root][1],add[root][2]);
add[root][0]=add[root][1]=add[root][2]=0;
}
void Modify(int root,int l,int r,int x,int y,int val)
{
if(l>=x&&r<=y)
{
Pushnow(root,l,r,(ull)val*(L-1)*(L-1),(ull)2*val*(1-L),(ull)val);
return;
}
int mid=(l+r)>>1;
Pushdown(root,l,r,mid);
if(x<=mid) Modify(root<<1,l,mid,x,y,val);
if(y>mid) Modify(root<<1|1,mid+1,r,x,y,val);
Pushup(root);
}
ull Query(int root,int l,int r,int x,int y)
{
if(l>=x&&r<=y)
return sum[root][0]+sum[root][1]+sum[root][2];
ull ans=0;int mid=(l+r)>>1;
Pushdown(root,l,r,mid);
if(x<=mid) ans+=Query(root<<1,l,mid,x,y);
if(y>mid) ans+=Query(root<<1|1,mid+1,r,x,y);
return ans;
}
int main()
{
freopen("rneaty.in","r",stdin);
freopen("rneaty.out","w",stdout);
int s,i,x;ull ans=0;
scanf("%d%d",&n,&m);
for(i=1;i<=n;++i)
{
S[i][0]=S[i-1][0]+(ull)i;
S[i][1]=S[i-1][1]+(ull)i*i;
}
for(i=1;i<=m;++i)
{
scanf("%d%d%d",&s,&L,&R);
if(s==1) scanf("%d",&x),Modify(1,1,n,L,R,x);
if(s==2) ans^=Query(1,1,n,L,R);
}
printf("%llu",ans);
fclose(stdin);
fclose(stdout);
return 0;
}