• [BZOJ4066]简单题


    bzoj

    题意

    一个(n*n)的棋盘,每次单点修改,矩形求和。
    操作数(le2*10^5),强制在线,空间限制(20M)

    sol

    (CDQ),树套树都被卡掉了。
    所以(kd-tree)了解一下?
    查询的时候类似线段树的查询,如果当前区间是查询区间的子集那就直接加上和返回,如果没有交集也直接返回,否则继续往下查。
    复杂度(O(nlog n+msqrt n))

    code

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    int gi()
    {
    	int x=0,w=1;char ch=getchar();
    	while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    	if (ch=='-') w=0,ch=getchar();
    	while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    	return w?x:-x;
    }
    #define ls t[o].ch[0]
    #define rs t[o].ch[1]
    #define cmin(a,b) (a>b?a=b:a)
    #define cmax(a,b) (a<b?a=b:a)
    const int N = 2e5+5;
    int n,root,D,ans;
    struct node{
    	int d[2],val;
    	bool operator < (const node &b) const
    		{return d[D]<b.d[D];}
    }a[N];
    struct kdtree{int d[2],Min[2],Max[2],ch[2],val,sum;}t[N];
    void mt(int x,int y)
    {
    	t[x].sum+=t[y].sum;
    	cmin(t[x].Min[0],t[y].Min[0]);cmax(t[x].Max[0],t[y].Max[0]);
    	cmin(t[x].Min[1],t[y].Min[1]);cmax(t[x].Max[1],t[y].Max[1]);
    }
    int build(int l,int r,int d)
    {
    	D=d;int o=l+r>>1;
    	nth_element(a+l,a+o,a+r+1);
    	t[o].d[0]=t[o].Min[0]=t[o].Max[0]=a[o].d[0];
    	t[o].d[1]=t[o].Min[1]=t[o].Max[1]=a[o].d[1];
    	t[o].val=t[o].sum=a[o].val;
    	if (l<o) ls=build(l,o-1,d^1),mt(o,ls);else ls=0;
    	if (o<r) rs=build(o+1,r,d^1),mt(o,rs);else rs=0;
    	return o;
    }
    void query(int o,int x1,int y1,int x2,int y2)
    {
    	if (t[o].Min[0]>=x1&&t[o].Max[0]<=x2&&t[o].Min[1]>=y1&&t[o].Max[1]<=y2)
    	{
    		ans+=t[o].sum;return;
    	}
    	if (t[o].Min[0]>x2||t[o].Max[0]<x1||t[o].Min[1]>y2||t[o].Max[1]<y1)
    	{
    		return;
    	}
    	if (t[o].d[0]>=x1&&t[o].d[0]<=x2&&t[o].d[1]>=y1&&t[o].d[1]<=y2)
    		ans+=t[o].val;
    	if (ls) query(ls,x1,y1,x2,y2);if (rs) query(rs,x1,y1,x2,y2);
    }
    int main()
    {
    	gi();int opt=gi();
    	while (opt<3)
    		if (opt==1)
    		{
    			int x=gi()^ans,y=gi()^ans,v=gi()^ans;++n;
    			a[n].d[0]=t[n].d[0]=t[n].Min[0]=t[n].Max[0]=x;
    			a[n].d[1]=t[n].d[1]=t[n].Min[1]=t[n].Max[1]=y;
    			a[n].val=t[n].val=t[n].sum=v;
    			if (!root) root=n;
    			else for (int p=root,d=0;p;d^=1)
    			{
    				mt(p,n);
    				int &nxt=t[p].ch[t[n].d[d]>=t[p].d[d]];
    				if (!nxt) {nxt=n;break;}p=nxt;
    			}
    			if (n%10000==0) root=build(1,n,0);
    			opt=gi();
    		}
    		else
    		{
    			int x1=gi()^ans,y1=gi()^ans,x2=gi()^ans,y2=gi()^ans;
    			ans=0;query(root,x1,y1,x2,y2);printf("%d
    ",ans);
    			opt=gi();
    		}
    	return 0;
    }
    
  • 相关阅读:
    定位及CSS常见属性
    浮动及清浮动的方法
    C语言II博客作业04
    C语言II—作业03
    C语言II—作业02
    C语言II博客作业01
    期末总结
    C语言I博客作业09
    C语言I博客作业08
    C语言I博客作业07
  • 原文地址:https://www.cnblogs.com/zhoushuyu/p/8945850.html
Copyright © 2020-2023  润新知