• [bzoj4066/2683]简单题_KD-Tree


    简单题 bzoj-4066

    题目大意:n*n的棋盘,开始为均为0,支持:单点加权值,查询矩阵权值和,强制在线。

    注释:$1le nle 5cdot 10^5$,$1le m le 2cdot 10^5$。


    想法:KD-Tree裸题。

    所谓KD-Tree,就是一个看起来贼牛逼实际上我觉着也贼牛逼的暴力... ...

    算了,网上讲解一摞摞,不赘述。

    这里我们只需要在KD-Tree上维护子树和即可。单点加的话往上更新呗,或者换成删除+插入也能过。

    最后,附上丑陋的代码... ...

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define N 500010 
    using namespace std;
    struct data
    {
    	int p[2],maxn[2],minn[2],c[2],w,sum;
    }a[N];
    int d,root;
    inline bool cmp(const data &a,const data &b)
    {
    	return a.p[d]==b.p[d]?a.p[d^1]<b.p[d^1]:a.p[d]<b.p[d];
    }
    inline void pushup(int k,int s)
    {
    	a[k].maxn[0]=max(a[k].maxn[0],a[s].maxn[0]);
    	a[k].minn[0]=min(a[k].minn[0],a[s].minn[0]);
    	a[k].maxn[1]=max(a[k].maxn[1],a[s].maxn[1]);
    	a[k].minn[1]=min(a[k].minn[1],a[s].minn[1]);
    	a[k].sum+=a[s].sum;
    }
    int build(int l,int r,int now)
    {
    	int mid=(l+r)>>1;
    	d=now,nth_element(a+l,a+mid,a+r+1,cmp);
    	a[mid].maxn[0]=a[mid].minn[0]=a[mid].p[0];
    	a[mid].maxn[1]=a[mid].minn[1]=a[mid].p[1];
    	a[mid].sum=a[mid].w;
    	a[mid].c[0]=a[mid].c[1]=0;
    	if(l<mid)a[mid].c[0]=build(l,mid-1,now^1),pushup(mid,a[mid].c[0]);
    	if(r>mid)a[mid].c[1]=build(mid+1,r,now^1),pushup(mid,a[mid].c[1]);
    	return mid;
    }
    void ins(int x)
    {
    	int *t=&root;
    	d=0;
    	while(*t)pushup(*t,x),t=&a[*t].c[a[x].p[d]>a[*t].p[d]],d^=1;
    	*t=x;
    }
    int query(int k,int x1,int y1,int x2,int y2)
    {
    	if(!k||a[k].maxn[0]<x1||a[k].maxn[1]<y1||a[k].minn[0]>x2||a[k].minn[1]>y2)return 0;
    	if(a[k].maxn[0]<=x2&&a[k].maxn[1]<=y2&&a[k].minn[0]>=x1&&a[k].minn[1]>=y1)return a[k].sum;
    	int ans=0;
    	if(a[k].p[0]>=x1&&a[k].p[0]<=x2&&a[k].p[1]>=y1&&a[k].p[1]<=y2)ans+=a[k].w;
    	ans+=query(a[k].c[0],x1,y1,x2,y2)+query(a[k].c[1],x1,y1,x2,y2);
    	return ans;
    }
    int main()
    {
    	int opt,x1,y1,x2,y2,last=0,tot=0;
    	scanf("%*d");
    	while(scanf("%d",&opt)!=EOF&&opt!=3)
    	{
    		if(opt==1)
    		{
    			tot++,scanf("%d%d%d",&a[tot].p[0],&a[tot].p[1],&a[tot].w);
    			a[tot].p[0]^=last,a[tot].p[1]^=last,a[tot].w^=last,a[tot].sum=a[tot].w;
    			a[tot].maxn[0]=a[tot].minn[0]=a[tot].p[0];
    			a[tot].maxn[1]=a[tot].minn[1]=a[tot].p[1];
    			ins(tot);
    			if(tot%10000==0)root=build(1,tot,0);
    		}
    		else scanf("%d%d%d%d",&x1,&y1,&x2,&y2),x1^=last,y1^=last,x2^=last,y2^=last,printf("%d
    ",last=query(root,x1,y1,x2,y2));
    	}
    	return 0;
    }
    

    小结:KD-Tree更好玩... ...

  • 相关阅读:
    BZOJ 3997: [TJOI2015]组合数学 [偏序关系 DP]
    [Sdoi2017]新生舞会 [01分数规划 二分图最大权匹配]
    [Sdoi2017]相关分析 [线段树]
    [Sdoi2017]硬币游戏 [高斯消元 KMP]
    [Sdoi2017]序列计数 [矩阵快速幂]
    [Sdoi2017]树点涂色 [lct 线段树]
    [Sdoi2017]数字表格 [莫比乌斯反演]
    BZOJ 3160: 万径人踪灭 [fft manacher]
    Rabbitmq常见测试
    MQ(消息队列)功能介绍
  • 原文地址:https://www.cnblogs.com/ShuraK/p/9383758.html
Copyright © 2020-2023  润新知