bzoj
luogu
有乙個長度為\(n\) 的序列,有三個操作:
\(i \ \ a\ b\ c\ :\)表示將\([a,b]\)這一段區間的元素集體增加\(c\);
\(r \ \ a\ b\ :\)表示將\([a,b]\)區間內所有元素變成相反數;
\(q \ \ a\ b\ c\ :\)表示詢問\([a,b]\)這一段區間中選擇\(c\) 個數相乘的所有方案的和\(mod19940417\)的值。
對於100%的資料,\(n≤50000,q≤50000\),初始序列的元素的絕對值\(≤10^9\),保證\([a,b]\)是乙個合法區間,\(i\)操作中\(|c|\le10^9\),\(q\)操作中\(1≤c≤min(b−a+1,20)\)
維護的資訊就是在每乙個區間內選出\(0...20\)個數的乘積之和吧。
向上合併就是乙個類似卷積的形式,直接\(o(c^2)\)轉移即可。
區間取反簡單一些,就是把所有\(i\)為奇數的資訊取反即可。
加乙個數相對來說複雜一點,可以把原來的式子大力展開,得到了乙個組合數乘\(x\)的若干次冪之和的形式。
記得處理兩種標記合併的問題。
#include#includeusing namespace std;
int gi()
const int n = 5e4+5;
const int mod = 19940417;
struct datat[n<<2];
int n,m,c[n][21],tag[n<<2],rev[n<<2];
inline data operator + (data a,data b)
return c;
}void build(int x,int l,int r)
int mid=l+r>>1;
build(x<<1,l,mid);build(x<<1|1,mid+1,r);
t[x]=t[x<<1]+t[x<<1|1];
}inline void cover(int x,int l,int r,int v)
t[x]=a;(tag[x]+=v)%=mod;
}inline void reverse(int x)
inline void pushdown(int x,int l,int r)
if (tag[x]) }
void modify_tag(int x,int l,int r,int ql,int qr,int v)
pushdown(x,l,r);int mid=l+r>>1;
if (ql<=mid) modify_tag(x<<1,l,mid,ql,qr,v);
if (qr>mid) modify_tag(x<<1|1,mid+1,r,ql,qr,v);
t[x]=t[x<<1]+t[x<<1|1];
}void modify_rev(int x,int l,int r,int ql,int qr)
pushdown(x,l,r);int mid=l+r>>1;
if (ql<=mid) modify_rev(x<<1,l,mid,ql,qr);
if (qr>mid) modify_rev(x<<1|1,mid+1,r,ql,qr);
t[x]=t[x<<1]+t[x<<1|1];
}data query(int x,int l,int r,int ql,int qr)
int main()
build(1,1,n);
while (m--)
return 0;
}
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...