有乙個長度為n的序列,有三個操作1.i a b c表示將[a,b]這一段區間的元素集體增加c,2.r a b表示將[a,b]區間內所有元素變成相反數,3.q a b c表示詢問[a,b]這一段區間中選擇c個數相乘的所有方案的和mod 19940417的值。
第一行兩個數n,q表示序列長度和操作個數。
第二行n個非負整數,表示序列。
接下來q行每行輸入乙個操作i a b c或者 r a b或者q a b c意義如題目描述。
對於每個詢問,輸出選出c個數相乘的所有方案的和mod19940417的值。
5 51 2 3 4 5
i 2 3 1
q 2 4 2
r 1 5
i 1 3 -1
q 1 5 1
4019940397
樣例說明
做完第乙個操作序列變為1 3 4 4 5。
第一次詢問結果為3*4+3*4+4*4=40。
做完r操作變成-1 -3 -4 -4 -5。
做完i操作變為-2 -4 -5 -4 -5。
第二次詢問結果為-2-4-5-4-5=-20。
100%的資料n<=50000,q<=50000,初始序列的元素的絕對值<=109,i
a b c中保證[a,b]是乙個合法區間,|c|<=109,r a b保證[a,b]是個合法的區間。q a b
c中保證[a,b]是個合法的區間1<=c<=min(b-a+1,20)。
每個區間維護f[i]表示當c=i時這個區間的答案。
然後可以暴力合併區間的答案,上傳和查詢同理。
難點在於兩個修改。
取相反數的操作顯然只對i為奇數的f[i]取相反數,偶數不變。
區間加x時,假設從$$到$$,那麼$(a+x)*(b+x)+(b+x)*(c+x)+(a*x)+(c*x)=ab+ac+bc+2x(a+b+c)+3x^$。
有一些是我們已經知道的資訊,剩下的那些x的係數是組合數,預處理出來即可。
**:
#include #include #include using namespace std;#define n 50050
#define mod 19940417
#define ls p<<1
#define rs p<<1|1
int n,m,c[n][22];
struct node
node operator + (const node &x) const
}re.siz=siz+x.siz;
return re;
}void rev_()
void add_(int d)
node query(int l,int r,int x,int y,int p)
void update(int l,int r,int x,int y,int v,int p)
pushdown(p);
int mid=(l+r)>>1;
if(x<=mid) update(l,mid,x,y,v,ls);
if(y>mid) update(mid+1,r,x,y,v,rs);
t[p]=t[ls]+t[rs];
}void reverse(int l,int r,int x,int y,int p)
pushdown(p);
int mid=(l+r)>>1;
if(x<=mid) reverse(l,mid,x,y,ls);
if(y>mid) reverse(mid+1,r,x,y,rs);
t[p]=t[ls]+t[rs];
}char opt[10];
int main()
build(1,n,1);
while(m--) else if(opt[0]=='r') else
}}
BZOJ2962 序列操作
題目大意 給定n個數,要求支援區間加,區間取相反數,區間查詢任意選c c 20 個數的所有方案中乘積的和 和維護k次方的和很像,想要維護選c個數,就要把選1 c個數的方案全部維護出來 這樣當合併兩個區間的時候 pushup 只需要列舉左右區間分別取了幾個數即可 現在考慮兩種修改操作 1.區間取相反數...
bzoj2962 序列操作
有乙個長度為n的序列,有三個操作1.i a b c表示將 a,b 這一段區間的元素集體增加c,2.r a b表示將 a,b 區間內所有元素變成相反數,3.q a b c表示詢問 a,b 這一段區間中選擇c個數相乘的所有方案的和mod 19940417的值。第一行兩個數n,q表示序列長度和操作個數。第...
bzoj 2962 序列操作
time limit 50 sec memory limit 256 mb submit status discuss 有乙個長度為n的序列,有三個操作1.i a b c表示將 a,b 這一段區間的元素集體增加c,2.r a b表示將 a,b 區間內所有元素變成相反數,3.q a b c表示詢問 a...