线段树区间合并的题目套路就是每一段维护
1.当前段的答案data[k],
2.当前段所有前缀Left[k]
3.当前段所有后缀Right[k]
合并时由当前段的左右子节点的data转移当前段,
还有左子节点的后缀与右子节点的前缀合并形成的区间对当前段的贡献。
然后维护当前段Left,Right就ok了。
现在很少看见用vect或者map维护每一段前后缀的了(我会说是跑的太慢了吗)。
一般都会用组合数学优化一下或者二进制优化。
这里也不例外,当前段的每一个前后缀都是乘积Left,Right只是这些前后缀的和,
1.当前段的答案data[k],
2.当前段所有前缀Left[k]
3.当前段所有后缀Right[k]
合并时由当前段的左右子节点的data转移当前段,
还有左子节点的后缀与右子节点的前缀合并形成的区间对当前段的贡献。
然后维护当前段Left,Right就ok了。
现在很少看见用vect或者map维护每一段前后缀的了(我会说是跑的太慢了吗)。
一般都会用组合数学优化一下或者二进制优化。
这里也不例外,当前段的每一个前后缀都是乘积Left,Right只是这些前后缀的和,
合并原理类似多项式乘法,(和的乘积等于两个多项式的乘积)
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <map>
#define mid (l+r>>1)
#define lson k<<1,l,mid
#define rson k<<1|1,mid+1,r
using namespace std;
const int mod=10007;
const int maxn=1e5+7;
int data[maxn*4];
int Len[maxn*4];
int Left[maxn*4],Right[maxn*4];
void update(int k,int l,int r,int p,int v){
if(p<l||r<p)return ;
if(l==r){
Len[k]=Left[k]=Right[k]=data[k]=v%mod;
return ;
}
if(p<=mid) update(lson,p,v);
else update(rson,p,v);
data[k]=(data[k<<1]+data[k<<1|1])%mod;
data[k]=(data[k]+(Right[k<<1]*Left[k<<1|1])%mod)%mod;
Left[k]=((Len[k<<1]*Left[k<<1|1])%mod+Left[k<<1])%mod;
Right[k]=((Len[k<<1|1]*Right[k<<1])%mod+Right[k<<1|1])%mod;
Len[k]=(Len[k<<1]*Len[k<<1|1])%mod;
}
int main()
{
int n,q;
while(~scanf("%d%d",&n,&q)){
int siz=min(n*8,maxn*4);
fill(data,data+siz,0);
fill(Left,Left+siz,0);
fill(Right,Right+siz,0);
for(int i=0;i<q;i++){
int p,v;
scanf("%d%d",&p,&v);
update(1,1,n,p,v);
printf("%d\n",data[1]%mod);
}
}
return 0;
}
放上我SB的map。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <map>
#define mid (l+r>>1)
#define lson k<<1,l,mid
#define rson k<<1|1,mid+1,r
using namespace std;
const int mod=10007;
const int maxn=1e5+7;
int data[maxn*4];
int Len[maxn*4];
map<int,int > Left[maxn*4],Right[maxn*4];
map<int,int>::iterator it,ip;
void update(int k,int l,int r,int p,int v){//printf("k==%d l==%d r==%d\n",k,l,r);
if(p<l||r<p)return ;
if(l==r){
data[k]=v%mod;
Left[k].clear();
Right[k].clear();
Left[k][(v%mod)]=1;
Right[k][(v%mod)]=1;
Len[k]=v%mod;//printf("data[%d]==%d \n",k,data[k]);
return ;
}
if(p<=mid) update(lson,p,v);
else update(rson,p,v);
data[k]=(data[k<<1]+data[k<<1|1])%mod;
for(it=Right[k<<1].begin();it!=Right[k<<1].end();it++){
for(ip=Left[k<<1|1].begin();ip!=Left[k<<1|1].end();ip++){
int t1=it->first%mod,t2=it->second%mod,t3=ip->first%mod,t4=ip->second%mod;
//printf("k== %d t1=%d t2=%d t3=%d t4=%d\n",k,t1,t2,t3,t4);
int t5=((((t1*t3)%mod)*t2)%mod)*t4%mod;
data[k]=(data[k]+t5)%mod;
}
} //printf("haha\n");
Left[k].clear();
for(it=Left[k<<1|1].begin();it!=Left[k<<1|1].end();it++){
int t1=it->first%mod,t2=it->second%mod;
Left[k][(t1*Len[k<<1])%mod]=(Left[k][(t1*Len[k<<1])%mod]+t2)%mod;
}
for(it=Left[k<<1].begin();it!=Left[k<<1].end();it++)
Left[k][(it->first)%mod]=(Left[k][(it->first)%mod]+it->second)%mod;//printf("haha2\n");
///
Right[k].clear();//printf("%d %d\n",Right[k<<1].size(),Right[k<<1|1].size());
for(it=Right[k<<1].begin();it!=Right[k<<1].end();it++){
int t1=it->first%mod,t2=it->second%mod;//printf("k<<1==%d %d %d \n",k<<1,t1,t2);
Right[k][(t1*Len[k<<1|1])%mod]=(Right[k][(t1*Len[k<<1|1])%mod]+t2)%mod;
//Right[k].push_back((Right[k<<1][i]*Right[k<<1|1][0])%mod);//printf("Right[k]==%d*%d \n",Right[k<<1][i],Right[k<<1|1][0]);
}
for(it=Right[k<<1|1].begin();it!=Right[k<<1|1].end();it++)
Right[k][it->first%mod]=(Right[k][it->first%mod]+it->second%mod)%mod;//printf("haha3\n");
Len[k]=(Len[k<<1]*Len[k<<1|1])%mod; //printf("data[%d]==%d Len %d %d %d\n",k,data[k],Len[k],Len[k<<1],Len[k<<1|1]);
}
void debug(int k,int l,int r){
printf("debug k==%d data=%d Len=%d Left=%d Right=%d\n",k,data[k],Len[k],Left[k].size(),Right[k].size());
for(it=Left[k].begin();it!=Left[k].end();it++)printf("Left k==%d %d %d\n",k,it->first,it->second);
for(it=Right[k].begin();it!=Right[k].end();it++)printf("Right k==%d %d %d\n",k,it->first,it->second);
if(l==r)return ;
debug(lson);
debug(rson);
}
int main()
{
int n,q;
while(~scanf("%d%d",&n,&q)){
int siz=min(n*8,maxn*4);
fill(data,data+siz,0);
for(int i=0;i<siz;i++){
Left[i].clear();//Left[i][0]=1;
Right[i].clear();//Right[i][0]=1;
}//debug(1,1,n);
for(int i=0;i<q;i++){
int p,v;
scanf("%d%d",&p,&v);
update(1,1,n,p,v);
//printf("-----------\n");debug(1,1,n);printf("--------------\n");
printf("%d\n",data[1]%mod);
}
}
return 0;
}