题解:
前一题不是强制在线,后一题是强制在线
树套树空间会炸
说一下cdq分治+树状数组
首先我们利用cdq分治使得查询和操作保证先后关系
然后矩阵查询变成4个矩阵的差
那么我们就可以运用扫描线的方法来维护了
时间nlogn^2,空间O(n)
后一题是kd-tree
查询的方法和线段树基本一样
如果矩阵被包含就返回答案,如果不被包含就直接退出
否则递归下去
然后修改的话和替罪羊树一样
达到一定时候就重构
注意一下x相同insert和build要保证y的顺序区分左右
另外学习了一下map中用struct作为key的方法 虽然这题完全不用用
代码:
#include <bits/stdc++.h> using namespace std; #define rint register int #define IL inline #define rep(i,h,t) for (rint i=h;i<=t;i++) #define dep(i,t,h) for (rint i=t;i>=h;i--) #define mid ((h+t)/2) #define me(x) memset(x,0,sizeof(x)) const int INF=2e9; const int N=6e6+1e4; char ss[1<<24],*A=ss,*B=ss; IL char gc() {return A==B&&(B=(A=ss)+fread(ss,1,1<<24,stdin),A==B)?EOF:*A++; } template<class T>void read(T &x) {rint f=1,c; while (c=gc(),c<48||c>57) if (c=='-') f=-1; x=(c^48);while (c=gc(),c>47&&c<58) x=(x<<3)+(x<<1)+(c^48); x*=f; } IL void umax(int &x,int y) {if (x<y) x=y; } IL void umin(int &x,int y) {if (x>y) x=y; } struct re{int d[2],v; }p[N]; int cmp_d,ans,rt,num; bool cmp(re x,re y) {return x.d[cmp_d]<y.d[cmp_d]||(x.d[cmp_d]==y.d[cmp_d]&&x.d[cmp_d^1]<y.d[cmp_d^1]); } struct kd {int Mx[N],My[N],Nx[N],Ny[N],count2[N],ls[N],rs[N];IL void clear(){me(count2);me(ls); me(rs);}IL void updata(int x){count2[x]=count2[ls[x]]+count2[rs[x]]+p[x].v;if (ls[x]){umax(Mx[x],Mx[ls[x]]);umax(My[x],My[ls[x]]);umin(Nx[x],Nx[ls[x]]);umin(Ny[x],Ny[ls[x]]);}if (rs[x]){umax(Mx[x],Mx[rs[x]]);umax(My[x],My[rs[x]]);umin(Nx[x],Nx[rs[x]]);umin(Ny[x],Ny[rs[x]]);}}int build(int h,int t,int o){cmp_d=o; nth_element(p+h,p+mid,p+t+1,cmp);int x=mid;Mx[x]=Nx[x]=p[x].d[0];My[x]=Ny[x]=p[x].d[1];count2[x]=p[x].v;if (h!=x) ls[x]=build(h,mid-1,o^1); else ls[x]=0;if (x!=t) rs[x]=build(mid+1,t,o^1); else rs[x]=0;updata(x);return x; }void insert(int &k,int x,int y,int z,int o){if (!k){k=++num;Mx[num]=Nx[num]=p[num].d[0];My[num]=Ny[num]=p[num].d[1];count2[num]=p[num].v=z;return;}if (p[k].d[0]==x&&p[k].d[1]==y){count2[k]+=z; p[k].v+=z; return;}if (!o)if (x<p[k].d[0]||(x==p[k].d[0]&&y<p[k].d[1])) insert(ls[k],x,y,z,o^1);else insert(rs[k],x,y,z,o^1);else if (y<p[k].d[1]||(y==p[k].d[1]&&x<p[k].d[0])) insert(ls[k],x,y,z,o^1);else insert(rs[k],x,y,z,o^1); updata(k);}void query(int k,int x1,int x2,int y1,int y2){if (!k||Mx[k]<x1||Nx[k]>x2||My[k]<y1||Ny[k]>y2) return;if (x2>=Mx[k]&&Nx[k]>=x1&&y2>=My[k]&&Ny[k]>=y1){ans+=count2[k]; return;}if (x1<=p[k].d[0]&&p[k].d[0]<=x2&&y1<=p[k].d[1]&&p[k].d[1]<=y2)ans+=p[k].v;query(ls[k],x1,x2,y1,y2); query(rs[k],x1,x2,y1,y2);} }kd; struct re1{int a,b; }; struct cmp2 {bool operator() (const re1 x,const re1 y){if (x.a<y.a||(x.a==y.a&&x.b<y.b)) return(1); else return(0);} }; map<re1,int,cmp2> M; int main() {int m;freopen("1.in","r",stdin);freopen("1.out","w",stdout);read(m);int cnt=0,rt=0,i=0;while (1){i++;ans=0;int k;read(k);if (k==3) break;if (k==1){int x,y,z;read(x); read(y); read(z);x^=ans; y^=ans; z^=ans;re1 k3=(re1){x,y};int kk=M[k3];if (!kk) p[num+1].d[0]=x,p[num+1].d[1]=y,kk=num+1;M[k3]=kk;kd.insert(rt,x,y,z,0);cnt++;if (cnt%10000==0){ kd.clear();rt=kd.build(1,num,0);} } else{int x1,x2,y1,y2;read(x1),read(y1),read(x2),read(y2);x1^=ans,x2^=ans,y1^=ans,y2^=ans;ans=0;kd.query(rt,x1,x2,y1,y2);cout<<ans<<endl;}}return 0; }