description
solution
跟着各位dalao写了一下线段树分治的题
我们把修改和询问按照时间建立线段树分治,
对于每一个修改标记永久化,对于每一个区间进行区间覆盖
主要的想法就是对每一个线段树节点开一个\(vector\)记录所有的修改和询问
在线段树上的一条链上插入修改,使用区间覆盖的方法在线段树上插入询问
对整棵线段树进行\(dfs\),每次取出节点上的\(vector\)并对其进行处理
大概就是这样
void segdiv(int i,int l,int r){//线段树分治??? work(f[i],g[i]);if(l==r)return;segdiv(ls,l,mid);segdiv(rs,mid+1,r); } il void insertmodify(int i,int l,int r,int x,int y,modify mdf){ //这里是插入修改 f[i].push_back(mdf); if(l==r)return; if(x<=mid)insertmodify(ls,l,mid,x,y,mdf); else insertmodify(rs,mid+1,r,x,y,mdf); } il void insertquery(int i,int l,int r,int x,int y,ask q){ //这里是插入询问 if(y<x)return; if(x<=l&&r<=y){g[i].push_back(q);return;} if(x<=mid)insertquery(ls,l,mid,x,y,q); if(mid<y)insertquery(rs,mid+1,r,x,y,q); }
code
#include<bits/stdc++.h> #include<algorithm> #include<iostream> #include<cstdlib> #include<iomanip> #include<cstring> #include<complex> #include<vector> #include<cstdio> #include<string> #include<bitset> #include<ctime> #include<cmath> #include<queue> #include<stack> #include<map> #include<set> #define FILE "a" #define mp make_pair #define pb push_back #define RG register #define il inline using namespace std; typedef unsigned long long ull; typedef vector<int>VI; typedef long long ll; typedef double dd; const dd eps=1e-10; const int mod=1e9+7; const int N=1e5+10; const int T=5e6+10; const dd pi=acos(-1); const int inf=2147483647; const ll INF=1e18+1; il ll read(){ RG ll data=0,w=1;RG char ch=getchar(); while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar(); if(ch=='-')w=-1,ch=getchar(); while(ch<='9'&&ch>='0')data=data*10+ch-48,ch=getchar(); return data*w; } il void file(){ srand(time(NULL)+rand()); freopen(FILE".in","r",stdin); freopen(FILE".out","w",stdout); } struct modify{int a,b,day;}M[N]; bool cmp(modify x,modify y){return x.a<y.a;} struct ask{int id,a,b,c,d,e;}Q[N]; int n,m,day,mt,qt,ans[N],pw[21],tot,num[N],sz; vector<modify>f[N<<5]; vector<ask>g[N<<5]; int rt[N],s[N<<5][2],sum[N<<5]; il void insert(int cur,int lst,int val){ sum[cur]=sum[lst]+1;bool d; for(RG int i=17;~i;i--){ d=val&pw[i]; s[cur][d]=++tot;s[cur][!d]=s[lst][!d]; sum[s[cur][d]]=sum[s[lst][d]]+1; cur=s[cur][d];lst=s[lst][d]; } } il int query(int l,int r,int x){ if(l>r)return 0; l=rt[l-1];r=rt[r];bool d;int ret=0; for(RG int i=17;~i;i--){ d=x&pw[i]; if(sum[s[r][!d]]-sum[s[l][!d]]>0){ ret|=pw[i];r=s[r][!d];l=s[l][!d]; } else{r=s[r][d];l=s[l][d];} } return ret; } void work(vector<modify>F,vector<ask>G){ RG int ft=F.size(),gt=G.size(); tot=sz=0; for(RG int i=0;i<ft;i++){ num[++sz]=F[i].a; insert(rt[i+1]=++tot,rt[i],F[i].b); } for(RG int i=0,l,r;i<gt;i++){ l=lower_bound(num+1,num+sz+1,G[i].a)-num; r=upper_bound(num+1,num+sz+1,G[i].b)-num-1; ans[G[i].id]=max(ans[G[i].id],query(l,r,G[i].e)); } } #define ls (i<<1) #define rs (i<<1|1) #define mid ((l+r)>>1) il void insertmodify(int i,int l,int r,int x,int y,modify mdf){ f[i].push_back(mdf); if(l==r)return; if(x<=mid)insertmodify(ls,l,mid,x,y,mdf); else insertmodify(rs,mid+1,r,x,y,mdf); } il void insertquery(int i,int l,int r,int x,int y,ask q){ if(y<x)return; if(x<=l&&r<=y){g[i].push_back(q);return;} if(x<=mid)insertquery(ls,l,mid,x,y,q); if(mid<y)insertquery(rs,mid+1,r,x,y,q); } void segdiv(int i,int l,int r){ work(f[i],g[i]);if(l==r)return;segdiv(ls,l,mid);segdiv(rs,mid+1,r); } int main() { n=read();m=read();pw[0]=1;for(RG int i=1;i<=20;i++)pw[i]=pw[i-1]<<1; for(RG int i=1;i<=n;i++)insert(rt[i]=++tot,rt[i-1],read()); for(RG int i=1,o,a,b,c,d;i<=m;i++){ o=read(); if(!o){day++;a=read();b=read();M[++mt]=(modify){a,b,day};} else{ a=read();b=read();d=read();c=read(); Q[++qt]=(ask){qt,a,b,max(day-c,0)+1,day,d}; } } for(RG int i=1;i<=qt;i++) ans[i]=max(ans[i],query(Q[i].a,Q[i].b,Q[i].e)); sort(M+1,M+mt+1,cmp); for(RG int i=1;i<=mt;i++)insertmodify(1,1,day,M[i].day,day,M[i]); for(RG int i=1;i<=qt;i++) if(Q[i].d)insertquery(1,1,day,max(Q[i].c,1),Q[i].d,Q[i]); segdiv(1,1,day); for(RG int i=1;i<=qt;i++)printf("%d\n",ans[i]);return 0; }
来源:https://www.cnblogs.com/cjfdf/p/9379550.html