bzoj2683&&bzoj4066

题解:

前一题不是强制在线,后一题是强制在线

树套树空间会炸

说一下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; 
}

 

posted @ 2018-07-10 12:40  尹吴潇  阅读(204)  评论(0编辑  收藏  举报