对于一类有插入、删除(撤销插入)和整体查询操作的题目,可以考虑按时间分治(也可以叫线段树分治),就是对于每一个插入操作处理出它存在的时间,那么就不用管删除操作了,再将这些插入操作存在区间建立一棵时间线段树,每个节点是一个vector,然后从线段树dfs到叶子经过的点上所有点vector的并就是在这个点时会对其产生影响的所有操作了。而一般这类题不会真的要把所有vector传到叶子,可能是线性基之类的东西往下传......
例题:
T1 bzoj4184 shallot
基本是模板了......
代码:
#include<bits/stdc++.h>
#define pii pair<int,int>
#define fi first
#define sc second
#define pb(x) push_back(x)
using namespace std;
const int N=5e5+100;
const int Mxa=1<<30;
void rd(int &x)
{
char c=getchar();x=0;bool f=0;
while(!isdigit(c))f|=(c=='-'),c=getchar();
while(isdigit(c))x=x*10+c-48,c=getchar();
if(f)x=-x;
}
int n,a[N],ans[N];
struct xxj{
int a[31];
xxj(){memset(a,0,sizeof a);}
int& operator[](int x)
{return a[x];}
void ins(int x)
{
for(int i=30,j=Mxa;i>=0;i--,j>>=1)
{
if(x&j)
{
if(!a[i]){a[i]=x;break;}
x^=a[i];
}
}
}
int calc()
{
int nw=0;
for(int i=30;i>=0;i--)
if((nw^a[i])>nw)nw^=a[i];
return nw;
}
};
int fr_n,to_n;
pii fr[N],to[N];
vector<int>seg[N<<2];
void ins_seg(int L,int R,int l,int r,int k,int w)
{
if(L<=l&&r<=R)seg[k].pb(w);
else
{
int mid=(l+r)>>1;
if(L<=mid)ins_seg(L,R,l,mid,k<<1,w);
if(R>mid)ins_seg(L,R,mid+1,r,k<<1|1,w);
}
}
void dfs_seg(int l,int r,int k,xxj res)
{
for(int i=0;i<seg[k].size();i++)
res.ins(seg[k][i]);
if(l==r)
{
ans[l]=res.calc();
return;
}
else
{
int mid=(l+r)>>1;
dfs_seg(l,mid,k<<1,res);
dfs_seg(mid+1,r,k<<1|1,res);
}
}
int main()
{
rd(n);
for(int i=1;i<=n;i++)
rd(a[i]);
for(int i=1;i<=n;i++)
{
if(a[i]>0)fr[++fr_n]=pii(a[i],i);
else to[++to_n]=pii(-a[i],i);
}
sort(fr+1,fr+fr_n+1),sort(to+1,to+to_n+1);
int to_ps=0;
for(int i=1;i<=fr_n;i++)
{
while(to_ps<=to_n&&fr[i].fi>to[to_ps].fi)++to_ps;
//cerr<<fr[i].fi<<' '<<fr[i].sc<<' '<<to[to_ps].sc<<'\n';
if(to_ps<=to_n&&fr[i].fi==to[to_ps].fi)
{
ins_seg(fr[i].sc,to[to_ps].sc-1,1,n,1,fr[i].fi);
++to_ps;
}
else ins_seg(fr[i].sc,n,1,n,1,fr[i].fi);
}
dfs_seg(1,n,1,xxj());
for(int i=1;i<=n;i++)printf("%d\n",ans[i]);
}
T2 bzoj4644经典傻逼题
刚开始没想到,其实边权可以异或丢到点权上去,这样选取一条边两个点根据异或操作特性贡献抵消刚好满足题目求割边要求,这样这题与上面基本一样了,把线性基内的东西改成bitset即可。
#include<bits/stdc++.h>
#define Bst bitset<1005>
using namespace std;
const int N=505,M=1005;
template<class T>
void rd(T &x)
{
char c=getchar();x=0;bool f=0;
while(!isdigit(c))f|=(c=='-'),c=getchar();
while(isdigit(c))x=x*10+c-48,c=getchar();
if(f)x=-x;
}
struct xxj{
Bst a[M];
xxj(){};
void ins(Bst x)
{
for(int i=M-1;i>=0;i--)
{
if(!x[i])continue;
if(a[i].none()){a[i]=x;break;}
x^=a[i];
}
}
void print()
{
Bst res;
res.reset();
for(int i=M-1;i>=0;i--)
{
if(a[i].none())continue;
if(!res[i])res^=a[i];
}
bool flg=0;
for(int i=M-1;i>=0;i--)
{
if(!flg&&!res[i])continue;
putchar(res[i]?'1':'0'),flg=1;
}
flg?puts(""):puts("0");
}
};
Bst bf[N];
int n,m,las[N];
char s[M];
vector<Bst>seg[M<<2];
void ins_seg(int L,int R,int l,int r,int k,Bst x)
{
if(L<=l&&r<=R)seg[k].push_back(x);
else
{
int mid=(l+r)>>1;
if(L<=mid)ins_seg(L,R,l,mid,k<<1,x);
if(R>mid)ins_seg(L,R,mid+1,r,k<<1|1,x);
}
}
void dfs_seg(int l,int r,int k,xxj res)
{
for(int i=0;i<seg[k].size();i++)
res.ins(seg[k][i]);
if(l==r)res.print();
else
{
int mid=(l+r)>>1;
dfs_seg(l,mid,k<<1,res),dfs_seg(mid+1,r,k<<1|1,res);
}
}
int main()
{
//cerr<<sizeof seg;
int ID,u,v,len;
rd(ID);
rd(n),rd(m);
Bst nw;
for(int tim=1;tim<=m;tim++)
{
rd(u),rd(v);
scanf("%s",s+1);
if(u==v)continue;
len=strlen(s+1);
nw.reset();
for(int i=0;i<len;i++)
nw[i]=(s[len-i]=='1'?1:0);
if(las[u])ins_seg(las[u],tim-1,1,m,1,bf[u]);
if(las[v])ins_seg(las[v],tim-1,1,m,1,bf[v]);
las[u]=las[v]=tim;
bf[u]^=nw,bf[v]^=nw;
}
for(int i=1;i<=n;i++)
ins_seg(las[i],m,1,m,1,bf[i]);
dfs_seg(1,m,1,xxj());
}