【BZOJ】【4066】简单题(强制在线)

KD-Tree



  KD-Tree的进阶姿势戳这里 http://zyfzyf.is-programmer.com/posts/92431.html

  为啥有种线段树&平衡树的即视感……(树形结构的相似性?)

  每次插入之后,判断下如果某个子树的size>父亲size*0.7,那么重构一下……(替罪羊树的即视感)

  查询的时候,如果当前点表示的坐标范围被查询范围完全包含,则直接返回sum;

  否则:当前点若在范围内则更新答案,左子树若不全在范围外则递归进入查询,右子树同理(线段树的即视感)

  

TLE:rebuild的时候,我没清当前点的min和max就直接build子树&Push_up(o)了……活该跪……

  1 /**************************************************************
  2     Problem: 4066
  3     User: Tunix
  4     Language: C++
  5     Result: Accepted
  6     Time:28400 ms
  7     Memory:11444 kb
  8 ****************************************************************/
  9
 10 //BZOJ 4066
 11 #include<cstdio>
 12 #include<cstring>
 13 #include<cstdlib>
 14 #include<iostream>
 15 #include<algorithm>
 16 #define rep(i,n) for(int i=0;i<n;++i)
 17 #define F(i,j,n) for(int i=j;i<=n;++i)
 18 #define D(i,j,n) for(int i=j;i>=n;--i)
 19 #define pb push_back
 20 using namespace std;
 21 typedef long long LL;
 22 inline int getint(){
 23     int r=1,v=0; char ch=getchar();
 24     for(;!isdigit(ch);ch=getchar()) if (ch==‘-‘) r=-1;
 25     for(; isdigit(ch);ch=getchar()) v=v*10-‘0‘+ch;
 26     return r*v;
 27 }
 28 const int N=200010,INF=1e9;
 29 /*******************template********************/
 30 int n,m,ans,D,cnt,p[N],tot,root;
 31 struct node{
 32     int d[2],mn[2],mx[2],l,r,D,size,sum,v;
 33     int& operator [] (int x){return d[x];}
 34 }t[N],now;
 35 inline bool cmp(int x,int y){return t[x][D]<t[y][D];}
 36
 37 #define L t[o].l
 38 #define R t[o].r
 39 #define mid (l+r>>1)
 40 inline void Push_up(int o){
 41     F(i,0,1){
 42         t[o].mn[i]=min(t[o].mn[i],min(t[L].mn[i],t[R].mn[i]));
 43         t[o].mx[i]=max(t[o].mx[i],max(t[L].mx[i],t[R].mx[i]));
 44     }
 45     t[o].sum=t[L].sum+t[R].sum+t[o].v;
 46     t[o].size=t[L].size+t[R].size+1;
 47 }
 48 inline int build(int l,int r,int dir){
 49     D=dir;
 50     nth_element(p+l,p+mid,p+r+1,cmp);
 51     int o=p[mid];
 52     t[o].D=dir;
 53     F(i,0,1) t[o].mn[i]=t[o].mx[i]=t[o][i];
 54     t[o].sum=t[o].v;
 55     L=l<mid ? build(l,mid-1,dir^1) : 0;
 56     R=mid<r ? build(mid+1,r,dir^1) : 0;
 57     Push_up(o);
 58     return o;
 59 }
 60 inline void dfs(int o){
 61     if (!o) return;
 62     dfs(L);
 63     p[++cnt]=o;
 64     dfs(R);
 65 }
 66 inline void rebuild(int &o){
 67     cnt=0;
 68     dfs(o);
 69     o=build(1,cnt,t[o].D);
 70 }
 71 inline void Insert(int &o,int dir){
 72     if (!o){
 73         o=++tot; t[o]=now;
 74         F(i,0,1) t[o].mn[i]=t[o].mx[i]=t[o][i];
 75         t[o].D=dir;
 76         t[o].size=1;
 77         t[o].sum=t[o].v;
 78         return;
 79     }
 80     if (now[dir]<t[o][dir]){
 81         Insert(L,dir^1);
 82         Push_up(o);
 83         if ((double)t[L].size>(double)t[o].size*0.7) rebuild(o);
 84     }
 85     else{
 86         Insert(R,dir^1);
 87         Push_up(o);
 88         if ((double)t[R].size>(double)t[o].size*0.7) rebuild(o);
 89     }
 90 }
 91 int query(int o,int x1,int y1,int x2,int y2){
 92     if (!o) return 0;
 93     if (t[o].mn[0]>=x1 && t[o].mn[1]>=y1 && t[o].mx[0]<=x2 && t[o].mx[1]<=y2)
 94         return t[o].sum;
 95     else{
 96         int ans=0;
 97         if (t[o][0]>=x1 && t[o][0]<=x2 && t[o][1]>=y1 && t[o][1]<=y2) ans+=t[o].v;
 98         if (t[L].mn[0]>x2 || t[L].mx[0]<x1 || t[L].mn[1]>y2 || t[L].mx[1]<y1) ;
 99         else ans+=query(L,x1,y1,x2,y2);
100         if (t[R].mn[0]>x2 || t[R].mx[0]<x1 || t[R].mn[1]>y2 || t[R].mx[1]<y1) ;
101         else ans+=query(R,x1,y1,x2,y2);
102         return ans;
103     }
104 }
105 void print(int o){
106     if (!o) return;
107     printf("%d t[o].mn[0]=%d t[o].mn[1]=%d t[o].mx[0]=%d t[o].mx[1]=%d\n",o,t[o].mn[0],t[o].mn[1],t[o].mx[0],t[o].mx[1]);
108     print(L);
109     print(R);
110 }
111 int main(){
112 #ifndef ONLINE_JUDGE
113     freopen("4066.in","r",stdin);
114     freopen("4066.out","w",stdout);
115 #endif
116     F(i,0,1) t[0].mn[i]=INF,t[0].mx[i]=-INF;
117     t[0].size=t[0].sum=t[0].v=0;
118
119     n=getint(); int cmd;
120     while(scanf("%d",&cmd)!=EOF && cmd<3){
121         if (cmd==1){
122             now[0]=getint()^ans,now[1]=getint()^ans,now.v=getint()^ans;
123             Insert(root,1);
124         }else{
125             int x1=getint()^ans,y1=getint()^ans,x2=getint()^ans,y2=getint()^ans;
126             printf("%d\n",ans=query(root,x1,y1,x2,y2));
127         }
128     }
129     return 0;
130 }

4066: 简单题

Time Limit: 50 Sec  Memory Limit: 20 MB
Submit: 297  Solved: 99
[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

Source

[Submit][Status][Discuss]

时间: 2024-10-05 09:32:11

【BZOJ】【4066】简单题(强制在线)的相关文章

bzoj 4066: 简单题 kd-tree

4066: 简单题 Time Limit: 50 Sec  Memory Limit: 20 MBSubmit: 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

[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 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 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这一列的值加到树状数组里,来更新右半边的所有询问,注意这