bzoj 4066: 简单题 kd-tree

4066: 简单题

Time Limit: 50 Sec  Memory Limit: 20 MB
Submit: 234  Solved: 82
[Submit][Status][Discuss]

Description

你有一个N*N的棋盘,每个格子内有一个整数,初始时的时候全部为0,现在需要维护两种操作:


命令


参数限制


内容


1 x y A


1<=x,y<=N,A是正整数


将格子x,y里的数字加上A


2 x1 y1 x2 y2


1<=x1<= x2<=N

1<=y1<= y2<=N


输出x1 y1 x2 y2这个矩形内的数字和


3



终止程序

Input

输入文件第一行一个正整数N。

接下来每行一个操作。每条命令除第一个数字之外,

均要异或上一次输出的答案last_ans,初始时last_ans=0。

Output

对于每个2操作,输出一个对应的答案。

Sample Input

4
1 2 3 3
2 1 1 3 3
1 1 1 1
2 1 1 0 7
3

Sample Output

3
5

HINT

数据规模和约定

1<=N<=500000,操作数不超过200000个,内存限制20M,保证答案在int范围内并且解码之后数据仍合法。

样例解释见OJ2683

kd-tree (不需要套替罪羊)不用解释了吧。。。。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define MAXN 300100
#define MAXT MAXN
#define INF 0x3f3f3f3f
struct kdt_node
{
        int lc,rc;
        int xmn,xmx;
        int ymn,ymx;
        int sum;
        int x,y;
}kdt[MAXT];
int topt=0;
inline void update(int now)
{
        kdt[now].xmn=min(kdt[now].x,min(kdt[kdt[now].lc].xmn,kdt[kdt[now].rc].xmn));
        kdt[now].xmx=max(kdt[now].x,max(kdt[kdt[now].lc].xmx,kdt[kdt[now].rc].xmx));
        kdt[now].ymn=min(kdt[now].y,min(kdt[kdt[now].lc].ymn,kdt[kdt[now].rc].ymn));
        kdt[now].ymx=max(kdt[now].y,max(kdt[kdt[now].lc].ymx,kdt[kdt[now].rc].ymx));
}
int x,y,v;
void Add_kdt(int &now,int d=0)
{
        if (!now)
        {
                now=++topt;
                kdt[now].x=x;
                kdt[now].y=y;
                update(now);
        }
        kdt[now].sum+=v;
        if (kdt[now].x==x && kdt[now].y==y)return ;
        if (!d)
        {
                if (x<=kdt[now].x)
                {
                        Add_kdt(kdt[now].lc,1-d);
                }else
                {
                        Add_kdt(kdt[now].rc,1-d);
                }
        }else
        {
                if (y<=kdt[now].y)
                {
                        Add_kdt(kdt[now].lc,1-d);
                }else
                {
                        Add_kdt(kdt[now].rc,1-d);
                }
        }
        update(now);
}
int x1,x2,y1,y2;
int Query_kdt(int now,int d)
{
        if (!now)return 0;
        if (kdt[now].xmn>=x1 && kdt[now].xmx<=x2 && kdt[now].ymn>=y1 && kdt[now].ymx<=y2)
                return kdt[now].sum;
        int ret=0;
        if (kdt[now].x<=x2 && kdt[now].x>=x1 && kdt[now].y<=y2 && kdt[now].y>=y1)ret+=kdt[now].sum-kdt[kdt[now].lc].sum-kdt[kdt[now].rc].sum;
        if (!d)
        {
                if (x1<=kdt[now].x)
                        ret+=Query_kdt(kdt[now].lc,1-d);
                if (x2>kdt[now].x)
                        ret+=Query_kdt(kdt[now].rc,1-d);
        }else
        {
                if (y1<=kdt[now].y)
                        ret+=Query_kdt(kdt[now].lc,1-d);
                if (y2>kdt[now].y)
                        ret+=Query_kdt(kdt[now].rc,1-d);
        }
        return ret;
}

int main()
{
    //  freopen("input.txt","r",stdin);
    //  freopen("output.txt","w",stdout);
        int n,m;
        scanf("%d",&n);
        int root=0;
        int opt=0;
        int lastans=0;
        kdt[0].xmn=kdt[0].ymn=INF;
        kdt[0].xmx=kdt[0].ymx=-INF;
        while (true)
        {
                scanf("%d",&opt);
                if (opt==1)
                {
                        scanf("%d%d%d",&x,&y,&v);
                        x^=lastans;y^=lastans;v^=lastans;
                        Add_kdt(root,0);
                }else if (opt==2)
                {
                        scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
                        x1^=lastans;x2^=lastans;y1^=lastans;y2^=lastans;
                        printf("%d\n",lastans=Query_kdt(root,0));
                }else
                {
                        break;
                }
        }
}
时间: 2024-12-20 14:20:29

bzoj 4066: 简单题 kd-tree的相关文章

BZOJ 4066 简单题(KD树)

[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=4066 [题目大意] 要求维护矩阵内格子加点和矩阵查询 [题解] 往KD树上加权值点,支持矩阵查询即可,每隔5000个插入暴力重构树. [代码] #include <cstdio> #include <algorithm> using namespace std; const int N=300000,INF=1e9; namespace KD_Tree{ struct

[bzoj 4066]简单题

传送门 Description 两个操作,往一个格子里加一个数和求给定矩形的权值和,强制在线,操作数\(\leq 200000\) Solution? 直接上KD-tree 为了保证树的形态较为优美 每加入\(10000\)个数后,对KD-tree进行重构 Code? #include<bits/stdc++.h> #define ll long long #define max(a,b) ((a)>(b)?(a):(b)) #define min(a,b) ((a)<(b)?(a

BZOJ 2683 简单题 ——CDQ分治

简单题 #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define F(i,j,k) for (int i=j;i<=k;++i) #define D(i,j,k) for (int i=j;i>=k;--i) #define maxn 2000005 int sum[maxn]; void a

BZOJ 2508 简单题 数学算法

题目大意:维护一个平面,支持三种操作: 0.加入一条直线(给的是两点式) 1.删除一条直线 2.询问到所有直线距离平方和最小的点 题解见 http://blog.sina.com.cn/s/blog_ab8386bc0101i1nj.html 我只是贴代码供参考的- - 注意我的abcdef和题解设的不一样- - 这简单题WA了两页- - #include <cmath> #include <cstdio> #include <cstring> #include <

bzoj 3687: 简单题

3687: 简单题 Time Limit: 10 Sec  Memory Limit: 512 MB Description 小呆开始研究集合论了,他提出了关于一个数集四个问题:1.子集的异或和的算术和.2.子集的异或和的异或和.3.子集的算术和的算术和.4.子集的算术和的异或和.    目前为止,小呆已经解决了前三个问题,还剩下最后一个问题还没有解决,他决定把这个问题交给你,未来的集训队队员来实现. Input 第一行,一个整数n.第二行,n个正整数,表示01,a2….,. Output 一行

bzoj 2683: 简单题

2683: 简单题 Time Limit: 50 Sec  Memory Limit: 128 MBSubmit: 1779  Solved: 720[Submit][Status][Discuss] Description 你有一个N*N的棋盘,每个格子内有一个整数,初始时的时候全部为0,现在需要维护两种操作: 命令 参数限制 内容 1 x y A 1<=x,y<=N,A是正整数 将格子x,y里的数字加上A 2 x1 y1 x2 y2 1<=x1<= x2<=N 1<

bzoj 2683 简单题 cdq分治

题面 题目传送门 解法 可以离线,那么就是非常简单的cdq分治了 只要把询问拆成4个,然后就变成了一个三维偏序问题 时间复杂度:\(O(q\ log^2\ n)\) 代码 #include <bits/stdc++.h> #define int long long #define N 1000010 using namespace std; template <typename node> void chkmax(node &x, node y) {x = max(x, y

bzoj 3687 简单题 - bitset

Description 小呆开始研究集合论了,他提出了关于一个数集四个问题: 1.子集的异或和的算术和. 2.子集的异或和的异或和. 3.子集的算术和的算术和. 4.子集的算术和的异或和.     目前为止,小呆已经解决了前三个问题,还剩下最后一个问题还没有解决,他决定把 这个问题交给你,未来的集训队队员来实现. Input 第一行,一个整数n. 第二行,n个正整数,表示01,a2….,. Output 一行,包含一个整数,表示所有子集和的异或和. Sample Input 21 3 Sampl

BZOJ 2683 简单题 cdq分治+树状数组

题意:链接 **方法:**cdq分治+树状数组 解析: 首先对于这道题,看了范围之后,二维的数据结构是显然不能过的,于是我们可能会考虑把一维排序之后另一位上数据结构什么的,然而cdq分治却能够很好的体现它的作用. 首先,对于每一个询问求和,显然是x在它左边的并且出现时间在它之前的所有的change对他可能会有影响. 我们按照x第一关键字,y第二关键字,操作第三关键字来排序所有的询问,然后在cdq的时候,每次递归处理左半区间,按照x动态的将y这一列的值加到树状数组里,来更新右半边的所有询问,注意这