bzoj4137 [FJOI2015]火星商店问题
比较容易想到的做法是线段树套字典树,修改操作时在字典树上经过的节点维护一个最近被访问过的时间,这样询问操作只经过满足时间条件的节点,时间复杂度O(NlogN^2)但是因为线段树每个节点都要套个字典树,这样的话空间是不够的,不过由于可以离线处理,我们可以先把每个修改和询问操作所访问的线段树节点保存下来,然后一个个节点去做,这样的话空间复杂度就可以保证了。
代码
1 #include<cstdio> 2 #include<set> 3 #include<vector> 4 #define N 1000010 5 #define M 10000010 6 using namespace std; 7 int l[N],r[N],n,m,i,a,typ,b,L,R,ti,ans[N],tot,p[N],cnt,flag; 8 int s[M][2],t[M]; 9 vector<pair<int,int> > vec[N]; 10 vector<int> id[N]; 11 void build(int x,int a,int b) 12 { 13 int m; 14 l[x]=a;r[x]=b; 15 if (b-a>1) 16 { 17 m=(a+b)>>1; 18 build(2*x,a,m); 19 build(2*x+1,m,b); 20 } 21 } 22 void insert(int x,int a,int b,pair<int,int> c,int typ) 23 { 24 int m; 25 if (typ==0) 26 { 27 vec[x].push_back(c); 28 id[x].push_back(typ); 29 } 30 if ((a<=l[x])&&(r[x]<=b)) 31 { 32 if (typ) 33 { 34 vec[x].push_back(c); 35 id[x].push_back(typ); 36 } 37 return; 38 } 39 m=(l[x]+r[x])>>1; 40 if (a<m) insert(2*x,a,b,c,typ); 41 if (m<b) insert(2*x+1,a,b,c,typ); 42 } 43 void cl(int x) 44 { 45 int i; 46 for (i=1;i<=17;i++) 47 { 48 p[17-i+1]=x%2; 49 x=x/2; 50 } 51 } 52 void change(int x,int y) 53 { 54 int now,i; 55 cl(x); 56 now=1; 57 for (i=1;i<=17;i++) 58 { 59 if (s[now][p[i]]==0) 60 s[now][p[i]]=++tot; 61 now=s[now][p[i]]; 62 t[now]=max(t[now],y); 63 } 64 } 65 int query(int x,int y) 66 { 67 int now,i,ans=0; 68 cl(x); 69 now=1; 70 for (i=1;i<=17;i++) 71 if ((s[now][1-p[i]])&&(t[s[now][1-p[i]]]>=y)) 72 { 73 now=s[now][1-p[i]]; 74 ans=ans+(1<<(17-i)); 75 } 76 else 77 now=s[now][p[i]]; 78 return ans; 79 } 80 void gao(int x) 81 { 82 int i,a,b; 83 for (i=1;i<=tot;i++) 84 s[i][0]=s[i][1]=t[i]=0; 85 tot=1; 86 for (i=0;i<vec[x].size();i++) 87 { 88 a=vec[x][i].first; 89 b=vec[x][i].second; 90 if (id[x][i]==0) 91 change(a,b); 92 else 93 ans[id[x][i]]=max(ans[id[x][i]],query(a,b)); 94 } 95 if (r[x]-l[x]==1) 96 return; 97 gao(2*x); 98 gao(2*x+1); 99 } 100 int main() 101 { 102 scanf("%d%d",&n,&m); 103 build(1,0,n); 104 for (i=1;i<=n;i++) 105 { 106 scanf("%d",&a); 107 insert(1,i-1,i,make_pair(a,m+1),0); 108 } 109 ti=1; 110 for (i=1;i<=m;i++) 111 { 112 scanf("%d",&typ); 113 if (typ==1) 114 { 115 scanf("%d%d%d%d",&L,&R,&a,&b); 116 insert(1,L-1,R,make_pair(a,ti-b+1),++cnt); 117 } 118 else 119 { 120 ti++; 121 scanf("%d%d",&a,&b); 122 insert(1,a-1,a,make_pair(b,ti),0); 123 } 124 } 125 gao(1); 126 for (i=1;i<=cnt;i++) 127 printf("%d\n",ans[i]); 128 }