1. 程式人生 > >2019.01.04 bzoj2962: 序列操作(線段樹+組合數學)

2019.01.04 bzoj2962: 序列操作(線段樹+組合數學)

傳送門
線段樹基礎題。
題意:要求維護區間區間中選擇 c c 個數相乘的所有方案的和( c 20 c\le20

),支援區間加,區間取負。


由於 c 20 c\le20 ,因此可以對於每個線段樹節點可以暴力維護 21 21

s u m sum 值,合併也很簡單,是一個卷積的形式 s u m
i = j = 0 i s u m j s u m i j sum_i=\sum_{j=0}^isum_jsum_{i-j}
可以用FFT優化一波(滑稽
區間取負並沒有什麼難度,對於 s u m i sum_i 來說,如果 i i 是偶數就並沒有什麼影響,如果 i i 是奇數把 s u m i sum_i 變成 s u m i -sum_i 即可。
關鍵在於區間加。
考慮到區間加對每個 s u m sum 的影響,我們把 a 1 a 2 . . . a n a_1a_2...a_n 變成了 ( a 1 + x ) ( a 2 + x ) . . . ( a n + x ) (a_1+x)(a_2+x)...(a_n+x) ,我們設這個區間長度為 l e n len ,那麼有組合數學的方法可以將這個式子展開: n e w s u m i = j = 0 i C l e n j i j x j o l d s u m j newsum_{i}=\sum_{j=0}^iC_{len-j}^{i-j}x^joldsum_j 相當於是列舉每個括號裡面 x x 的個數來更新答案

然後就沒啥了~~注意細節~~
程式碼:

#include<bits/stdc++.h>
#define lc (p<<1)
#define rc (p<<1|1)
#define mid (T[p].l+T[p].r>>1)
#define add(a,b) ((a)+(b)>=mod?(a)+(b)-mod:(a)+(b))
#define mul(a,b) ((ll)(a)*(b)%mod)
#define dec(a,b) ((a)>=(b)?(a)-(b):(a)-(b)+mod)
#define ri register int
using namespace std;
typedef long long ll;
const int mod=19940417,N=5e5+5;
int n,m,a[N],C[N][21];
inline int read(){
	int ans=0,w=1;
	char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
	while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
	return ans*w;
}
struct Node{int l,r,sum[21],add;bool rev;Node(){l=r=add=rev=0;for(ri i=0;i<=20;++i)sum[i]=0;}}T[N<<2];
inline Node operator+(const Node&a,const Node&b){
	Node ret;
	ret.l=a.l,ret.r=b.r;
	for(ri i=0;i<=20;++i)for(ri j=0;j<=i;++j)ret.sum[i]=add(ret.sum[i],mul(a.sum[j],b.sum[i-j]));
	return ret;
}
inline void pushadd(int p,int v){
	T[p].add=add(T[p].add,v);
	for(ri i=min(T[p].r-T[p].l+1,20),len=T[p].r-T[p].l+1;~i;--i)for(ri j=i-1,mult=v;~j;--j,mult=mul(mult,v))
		T[p].sum[i]=add(T[p].sum[i],mul(C[len-j][i-j],mul(mult,T[p].sum[j])));
}
inline void pushrev(int p){
	T[p].rev^=1,T[p].add=dec(0,T[p].add);
	for(ri i=0;i<=20;++i)if(i&1)T[p].sum[i]=dec(0,T[p].sum[i]);
}
inline void pushdown(int p){
	if(T[p].rev)pushrev(lc),pushrev(rc),T[p].rev^=1;
	if(T[p].add)pushadd(lc,T[p].add),pushadd(rc,T[p].add),T[p].add=0;
}
inline void build(int p,int l,int r){
	T[p].l=l,T[p].r=r;
	if(T[p].l==T[p].r){T[p].sum[0]=1,T[p].sum[1]=a[l];return;}
	build(lc,l,mid),build(rc,mid+1,r),T[p]=T[lc]+T[rc];
}
inline void update(int p,int ql,int qr,int v){
	if(ql<=T[p].l&&T[p].r<=qr)return v?pushadd(p,v):pushrev(p);
	pushdown(p);
	if(qr<=mid)update(lc,ql,qr,v);
	else if(ql>mid)update(rc,ql,qr,v);
	else update(lc,ql,mid,v),update(rc,mid+1,qr,v);
	T[p]=T[lc]+T[rc];
}
inline Node query(int p,int ql,int qr){
	if(ql<=T[p].l&&T[p].r<=qr)return T[p];
	pushdown(p);
	if(qr<=mid)return query(lc,ql,qr);
	if(ql>mid)return query(rc,ql,qr);
	return query(lc,ql,mid)+query(rc,mid+1,qr);
}
inline void init(){
	for(ri i=0;i<=n;++i)C[i][0]=1;
	for(ri i=1;i<=n;++i){
		C[i][1]=i;
		for(ri j=2;j<=min(20,i);++j)C[i][j]=add(C[i-1][j],C[i-1][j-1]);
	}
	build(1,1,n);
}
int main(){
	n=read(),m=read();
	for(ri i=1;i<=n;++i)a[i]=(read()%mod+mod)%mod;
	init();
	while(m--){
		char s[2];
		scanf("%s",s);
		int l=read(),r=read(),v;
		if(s[0]=='I'){
			v=(read()%mod+mod)%mod;
			if(!v)continue;
			update(1,l,r,v);
		}
		else if(s[0
            
           

相關推薦

2019.01.04 bzoj2962: 序列操作線段+組合數學

傳送門 線段樹基礎題。 題意:要求維護區間區間中選擇 c c c個數相乘的所有方案的和(

bzoj4821 && luogu3707 SDOI2017相關分析線段數學

size .... 原來 node ans str 基本 其中 sdi 題目大意 給定n個元素的數列,每一個元素有x和y兩種元素,現在有三種操作: \(1\ L\ R\) 設\(xx\)為\([l,r]\)的元素的\(x_i\)的平均值,\(yy\)同理 求 \(\fr

BZOJ_1858_[Scoi2010]序列操作_線段

個數 brush build 接下來 inpu content con 線段 void BZOJ_1858_[Scoi2010]序列操作_線段樹 Description lxhgww最近收到了一個01序列,序列裏面包含了n個數,這些數要麽是0,要麽是1,現在對於這個

BZOJ_2962_序列操作_線段

列操作 scan min 組合 -a %d 假設 scanf 輸出 Description   有一個長度為n的序列,有三個操作1.I a b c表示將[a,b]這一段區間的元素集體增加c,2.R a b表示將[a,b]區間內所有元素變成相反數,3.Q a b c表示

bzoj1798: [Ahoi2009]Seq 維護序列seq線段多重標記下傳

ron add 表示 esp pro fine names 引號 線段 www.cnblogs.com/shaokele/ bzoj1798: [Ahoi2009]Seq 維護序列seq   Time Limit: 30 Sec   Memory Limit: 64 M

bzoj1798: [Ahoi2009]Seq 維護序列seq線段

區間 mod ans get 點子 return inline 處理 getch bzoj1798 題目描述:給定n個數的序列,有三種操作。 ?????1、將一段區間乘上c ?????2、將一段區間加上c ?????3、求一段區間的和 輸入格式:第一行兩個整數第一行兩個整數

【bzoj2333 & luoguP3273】棘手的操作線段合併

  題目傳送門:bzoj2333 luoguP3273   這操作還真“棘手”。。聽說這題是可並堆題?然而我不會可並堆。於是我就寫了線段數合併,然後調了一晚上,資料結構毀一生!!!QAQ……   其實這題也可以把合併強行看成樹上的關係然後dfs序後直接線段樹的,然而我菜啊。。看到連邊就只能想到線

2018.10.02 NOIP模擬 序列維護線段+廣義尤拉定理

描述 給出一個長度為n的序列,每個位置有個數字Ai,有2個操作: 1、區間修改,將[L,R]區間的數字加上一個數 2、區間查詢[l,r] 查詢:alal+1al+2....armodpa_l^{a_{l+1}^{a_{l+2}^{\text{....}^{a_r

[SCOI2010]序列操作 BZOJ1858 線段

dll san true 序列 lse 端點 是否 dst == 題目描述 lxhgww最近收到了一個01序列,序列裏面包含了n個數,這些數要麽是0,要麽是1,現在對於這個序列有五種變換操作和詢問操作: 0 a b 把[a, b]區間內的所有數全變成0 1 a b 把[a

2018.11.01 NOIP訓練 圖論線段+倍增+dfs序

傳送門 一道挺妙的題。 對於詢問點(u,v),如右圖所示,我們可以發現存在一個點m在u->v的路徑中,m子樹的點到u是最近的,m子樹外到v是最近的。其中dis(u,m)=(dis(u,v)-1)/2,且deep[u]>deep[v] 根據這個結論

P2023 [AHOI2009]維護序列 題解線段

題目連結 P2023 [AHOI2009]維護序列 解題思路 線段樹板子。不難,但是...有坑。坑有多深?一頁\(WA\)。 由於乘法可能乘\(k=0\),我這種做法可能會使結果產生負數。於是就有了這篇題解。 (詳情見程式碼註釋) AC程式碼 #include<stdio.h> #def

[51nod 1208] Stars in Your Window線段,掃描線

51nod clas html 題目 val col while cto pro 題目鏈接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1208 題意:也是矩形框點問題,不過每個點有權值,希望

HDU 4027 Can you answer these queries?線段區間開方

sizeof sqrt .cn swap %d nes nts following clr Can you answer these queries? Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 6576

51nod 1463 找朋友線段+離線處理

query max nbsp update ring tdi 包含 覆蓋 vector http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1463 題意: 思路: 好題! 先對所有查

HDU 3974 Assign the task線段 時間戳

truct stream char %d 節點 正在 原因 scanf 全部 題目鏈接:http://acm.split.hdu.edu.cn/showproblem.php?pid=3974 題意:n名員工組成一棵樹,分配任務給其中一名員工,那麽他和他的手下(就是該節點

最簡單的問題重慶市第八屆大學生程序設計大賽D 線段+離線思想

return ans img 個數 pre 子序列 clear 可持久化 sort 考場上的時候直接一臉懵逼了,啥? 區間裏面又要求子區間,還TM有上下界? 略加思索後倒是發現沒有那麽麻煩,因為很容易得出如下結論: 1.對於一個滿足條件的區間[L , R],對於他所有

HDU 1264 Counting Squares(Hash)或者線段+線掃描

bsp pan 解決 printf 就是 大小 lag 線段 ash http://acm.hdu.edu.cn/showproblem.php?pid=1264 題意:給你矩形的左下角和右上角兩個坐標,讓你求這些矩形覆蓋的面積的大小!~ 分析:一看就是線段樹+線掃描的問題

2017 ICPC 西安站現場賽 A.XOR 線段+線性基

getchar tput 線性 calculate ext following case all pri XORConsider an array A with n elements. Each of its element is A[i] (1 ≤ i ≤ n). Th

Lost Cows線段+二分判定

div ascend printf for () instead site uil red 4835: [Usaco2003 Open]Lost Cows Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 21 Solved:

降臨線段優化dp

main spa space odi pri line 除了 發現 獲得 降臨 選定點i會有代價\(c_i\),如果一個區間j內的點全被選擇,就可以獲得回報\(p_j\)。點數和區間個數\(<1e5\)。 還以為是線段樹優化網絡流(50萬個點200萬條邊看上去很可