【bzoj4066】 简单题

http://www.lydsy.com/JudgeOnline/problem.php?id=4066 (题目链接)

题意

  维护一个矩阵,两个操作,给某一个元素加上A,求其中一个子矩阵的元素之和。强制在线。

Solution

  KDtree,其它的就是跟平衡树的维护差不多。

  然而我现在还是TLE啊T_T,但是正确性拍过没问题,求大佬帮忙看看哪里挂了T_T

细节

  注意重新构树的时候,叶子节点的左右儿子要重新赋为0,因为最初它们的左右儿子并不是0。

代码

// bzoj4066
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<ctime>
#define LL long long
#define inf 1<<30
#define Pi acos(-1.0)
#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
using namespace std;
inline int gi() {
	int x=0,f=1;char ch=getchar();
	while (ch<‘0‘ || ch>‘9‘) {if (ch==‘-‘) f=-1;ch=getchar();}
	while (ch>=‘0‘ && ch<=‘9‘) {x=x*10+ch-‘0‘;ch=getchar();}
	return x*f;
}

const int maxn=200010;
int n,K,sz,rt;
LL ans;

struct KDtree {
	int val,l,r,v[2],mx[2],mn[2];
	LL sum;
	friend bool operator < (const KDtree a,const KDtree b) {
		return a.v[K]<b.v[K];
	}
}tr[maxn],t[maxn],S;

void update(int k) {
	for (int i=0;i<=1;i++) {
		if (tr[k].l) {
			tr[k].mn[i]=min(tr[tr[k].l].mn[i],tr[k].mn[i]);
			tr[k].mx[i]=max(tr[tr[k].l].mx[i],tr[k].mx[i]);
		}
		if (tr[k].r) {
			tr[k].mn[i]=min(tr[tr[k].r].mn[i],tr[k].mn[i]);
			tr[k].mx[i]=max(tr[tr[k].r].mx[i],tr[k].mx[i]);
		}
	}
	tr[k].sum=tr[k].val+tr[tr[k].l].sum+tr[tr[k].r].sum;
}
void insert(int &k,int p) {
	K=p;
	if (!k) {tr[k=++sz]=S;return;}
	if (S.v[0]==tr[k].v[0] && S.v[1]==tr[k].v[1]) {
		tr[k].val+=S.val,tr[k].sum+=S.val;
		return;
	}
	if (S<tr[k]) insert(tr[k].l,p^1);
	else insert(tr[k].r,p^1);
	update(k);
}
bool in(int x1,int y1,int X1,int Y1,int x2,int y2,int X2,int Y2) {
	return x1>=x2 && X1<=X2 && y1>=y2 && Y1<=Y2;
}
bool out(int x1,int y1,int X1,int Y1,int x2,int y2,int X2,int Y2) {
	return X1<x2 || x1>X2 || Y1<y2 || y1>Y2;
}
LL query(int k,int x,int y,int X,int Y) {
	if (!k) return 0;
	LL tmp=0;
	if (in(tr[k].mn[0],tr[k].mn[1],tr[k].mx[0],tr[k].mx[1],x,y,X,Y)) return tr[k].sum;
	if (out(tr[k].mn[0],tr[k].mn[1],tr[k].mx[0],tr[k].mx[1],x,y,X,Y)) return 0;
	if (in(tr[k].v[0],tr[k].v[1],tr[k].v[0],tr[k].v[1],x,y,X,Y)) tmp+=tr[k].val;
	tmp+=query(tr[k].l,x,y,X,Y)+query(tr[k].r,x,y,X,Y);
	return tmp;
}
int rebuild(int l,int r,int p) {
	K=p;
	int mid=(l+r)>>1;
	nth_element(t+l,t+mid,t+r+1);
	tr[mid]=t[mid];
	tr[mid].l=l<mid ? rebuild(l,mid-1,p^1) : 0;   //如果不赋值为0的话之后查询或插入时就会RE
	tr[mid].r=r>mid ? rebuild(mid+1,r,p^1) : 0;
	update(mid);
	return mid;
}
int main() {
	n=gi();
	ans=0;
	for (int op,x1,y1,x2,y2,A,m=10000;1;) {
		op=gi();if (op==3) break;
		x1=gi()^ans,y1=gi()^ans;
		if (op==1) {
			A=gi()^ans;
			S.v[0]=x1;S.v[1]=y1;S.sum=S.val=A;
			S.mx[0]=S.mn[0]=x1;S.mx[1]=S.mn[1]=y1;
			insert(rt,0);
			if (sz==m) {
				//printf("%.3lf ",(double)clock()/CLOCKS_PER_SEC);
				for (int i=1;i<=m;i++) t[i]=tr[i];
				rt=rebuild(1,m,0);m+=10000;
				//printf("%.3lf\n",(double)clock()/CLOCKS_PER_SEC);
			}
		}
		else {
			x2=gi()^ans,y2=gi()^ans;
			ans=query(rt,x1,y1,x2,y2);
			printf("%lld\n",ans);
		}
	}
	//printf("%.3lf ",(double)clock()/CLOCKS_PER_SEC);
	return 0;
}
时间: 2024-08-23 09:56:47

【bzoj4066】 简单题的相关文章

[BZOJ2683][BZOJ4066]简单题

试题描述 你有一个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 无 终止程序 输入 输入文件第一行一个正整数N. 接下来每行一个操作.每条命令除第一个数字之外, 均要异或上一次输出的答案last

【kd-tree】bzoj4066 简单题

同p1176. #include<cstdio> #include<cmath> #include<algorithm> using namespace std; #define N 200011 #define KD 2//ά¶ÈÊý int qp[2][2]; int n,root=1,m; bool dn; struct Node { int minn[KD],maxx[KD],p[KD],w,ch[2],sumv; void Init() { for(int

Bzoj4066 简单题

Time Limit: 50 Sec  Memory Limit: 20 MBSubmit: 2185  Solved: 581 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这个矩形内

【BZOJ4066】简单题 KDtree

[BZOJ4066]简单题 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. 接下来每行一个操作.每条命令除第

[bzoj4066/2683]简单题_KD-Tree

简单题 bzoj-4066 题目大意:n*n的棋盘,开始为均为0,支持:单点加权值,查询矩阵权值和,强制在线. 注释:$1\le n\le 5\cdot 10^5$,$1\le m \le 2\cdot 10^5$. 想法:KD-Tree裸题. 所谓KD-Tree,就是一个看起来贼牛逼实际上我觉着也贼牛逼的暴力... ... 算了,网上讲解一摞摞,不赘述. 这里我们只需要在KD-Tree上维护子树和即可.单点加的话往上更新呗,或者换成删除+插入也能过. 最后,附上丑陋的代码... ... #in

poj2105 IP Address(简单题)

题目链接:http://poj.org/problem?id=2105 Description Suppose you are reading byte streams from any device, representing IP addresses. Your task is to convert a 32 characters long sequence of '1s' and '0s' (bits) to a dotted decimal format. A dotted decima

poj 3270 Cow Sorting 置换群 简单题

假设初始状态为 a:2 3 1 5 4 6 则目标状态为 b:1 2 3 4 5 6且下标为初始状态中的3 1 2 4 5 6(a[3],a[1]...) 将置换群写成循环的形式 (2,3,1),(5,4),6就不用移动了. 移动方式2种 1:选循环内最小的数和其他len-1个数交换 2:选整个序列最小的数和循环内最小的数交换,转到1,再换回来. #include<cstdio> #include<queue> #include<algorithm> #include&

数论 --- 简单题

吃糖果 Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Total Submission(s): 22376    Accepted Submission(s): 6396 Problem Description HOHO, 终于从Speakless手上赢走了所有的糖果,是Gardon吃糖果时有个特殊的癖好,就是不喜欢将一样的糖果放在一起吃,喜欢先吃一种,下一次吃另一 种,这样:

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

HNU 12868 Island (简单题)

题目链接:http://acm.hnu.cn/online/?action=problem&type=show&id=12868&courseid=272 解题报告:输入n*m的地图,+表示土地,-表示水,要你求这个海岛的海岸线有多长,扫一遍就可以了. 1 #include<cstdio> 2 const int maxn = 2000; 3 char map[maxn][maxn]; 4 int _x[4] = {-1,0,1,0}; 5 int _y[4] = {0