记录编号 151698 评测结果 AAAAAAAAAAAAAAAAAAAA
题目名称 [国家集训队2012]Attack 最终得分 100
用户昵称 Gravatar天一阁 是否通过 通过
代码语言 C++ 运行时间 21.055 s
提交时间 2015-03-09 18:59:08 内存使用 256.77 MiB
显示代码纯文本
//attack
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>

#define l(x) ch[x][0]
#define r(x) ch[x][1]

const int Maxn=60010,Maxm=10010,Maxb=1050;
const int INF=0x3f3f3f3f;

using namespace std;

struct node{
	int x,y,v,pos;
}P[Maxn];

struct Asks{
	int type,x0,y0,x1,y1,k,v;
}A[Maxm];

int m,n,tot=0,ch[20000010][2],sumt[20000010];
int rank[Maxn],X[Maxn],bein[Maxn];
vector<int> lim,nodes[2];

int build(int l,int r){
	int x=++tot; sumt[x]=0;
	if(l==r) return x;
	int mid=(l+r)>>1;
	l(x)=build(l,mid);
	r(x)=build(mid+1,r);
	return x;
}

bool cmp_(node a,node b){
	return a.y<b.y;
}

int insert(int o,int l,int r,int qx){
	int x=++tot;
	l(x)=l(o); r(x)=r(o); sumt[x]=sumt[o]+1;
	if(l==r) return x;
	int mid=(l+r)>>1;
	if(qx<=mid) l(x)=insert(l(o),l,mid,qx);
	else r(x)=insert(r(o),mid+1,r,qx);
	return x;
}

int av[Maxn],Nv,tot_v=0,tot_x=0;

struct Block{
	node P[Maxb];
	int Y[Maxb],siz,mem_begin,root[Maxb],num;
	void add_node(node a){
		P[++siz]=a;
	}
	void make_tree(){
		tot=mem_begin;
		root[0]=1;
		for(int i=1;i<=siz;i++)
			root[i]=insert(root[i-1],1,Nv,P[i].v);
	}
	int calc(int x0,int y0,int x1,int y1,int L,int R){
		int ans=0;
		for(int i=1;i<=siz;i++)
			if(P[i].x<=x1&&P[i].x>=x0&&P[i].y<=y1&&P[i].y>=y0)
			    ans+=(P[i].v<=R&&P[i].v>=L? 1:0);
		return ans;
	}
	void init(){
		sort(P+1,P+siz+1,cmp_);
		make_tree();
		Y[0]=-INF; Y[siz+1]=INF;
		for(int i=1;i<=siz;i++)
		    bein[P[i].pos]=num,rank[P[i].pos]=i,Y[i]=P[i].y;
	}
}B[Maxb]={0};

int belong[Maxn],cntB;

bool cmpx(node a,node b){
	return a.x<b.x;
}

void move(int x){
	for(int i=0;i<nodes[0].size();i++)
		nodes[0][i]=ch[nodes[0][i]][x],nodes[1][i]=ch[nodes[1][i]][x];
}

int _queryL(int x0,int y0,int x1,int y1,int L,int R){
	int ans=0,mid=(L+R)>>1;
	for(int i=0;i<lim.size();i++) ans+=B[lim[i]].calc(x0,y0,x1,y1,L,mid);
	for(int i=0;i<nodes[0].size();i++){
		ans+=sumt[l(nodes[1][i])];
		ans-=sumt[l(nodes[0][i])];
	}
	return ans;
}

int _query(int x0,int y0,int x1,int y1,int L,int R){
	int ans=0;
	for(int i=0;i<lim.size();i++) ans+=B[lim[i]].calc(x0,y0,x1,y1,L,R);
	for(int i=0;i<nodes[0].size();i++){
		ans+=sumt[nodes[1][i]];
		ans-=sumt[nodes[0][i]];
	}
	return ans;
}

void Push_in(int l,int r,int yL,int yR){
	int lb=belong[l],rb=belong[r];
	lim.clear(); nodes[0].clear(); nodes[1].clear();
	lim.push_back(lb);
	if(lb!=rb) lim.push_back(rb);
	int lt,rt;
	for(int i=lb+1;i<rb;i++){
		lt=lower_bound(B[i].Y,B[i].Y+B[i].siz+2,yL)-B[i].Y;
		rt=upper_bound(B[i].Y,B[i].Y+B[i].siz+2,yR)-B[i].Y-1;
		rt=min(rt,B[i].siz),lt=max(lt,1);
		if(!rt) continue;
		nodes[0].push_back(B[i].root[lt-1]);
		nodes[1].push_back(B[i].root[rt]);
	}
}

void query(int x0,int y0,int x1,int y1,int k){
	if(x0>x1) swap(x0,x1);
	if(y0>y1) swap(y0,y1);
	int Lx=lower_bound(X,X+n+2,x0)-X;
	int Rx=upper_bound(X,X+n+2,x1)-X-1;
	if(!Rx){
		puts("It doesn't exist.");
		return;
	}
	Rx=min(Rx,n),Lx=max(Lx,1);
	Push_in(Lx,Rx,y0,y1);
	int l=1,r=Nv;
	if(_query(x0,y0,x1,y1,l,r)<k){
		puts("It doesn't exist.");
		return;
	}
	while(l<r){
		int tmp=_queryL(x0,y0,x1,y1,l,r),mid=(l+r)>>1;
		if(tmp<k) k-=tmp,l=mid+1,move(1);
		else r=mid,move(0);
	}
	printf("%d\n",av[l]);
}

void init(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++){
		scanf("%d%d%d",&P[i].x,&P[i].y,&P[i].v);
		P[i].pos=i;
		av[++tot_v]=P[i].v;
	}
	sort(P+1,P+n+1,cmpx);
	for(int i=1;i<=n;i++) X[i]=P[i].x;
	char str[11];
	for(int i=1;i<=m;i++){ 
		scanf("%s%d%d",str,&A[i].x0,&A[i].y0);
		A[i].type= str[0]=='Q';
		if(A[i].type) scanf("%d%d%d",&A[i].x1,&A[i].y1,&A[i].k);
		else A[i].x0++,A[i].y0++;
	}
	sort(av+1,av+tot_v+1);
	Nv=1;
	for(int i=2;i<=tot_v;i++)
	    if(av[i]!=av[i-1]) av[++Nv]=av[i];
	for(int i=1;i<=n;i++)
		P[i].v=lower_bound(av+1,av+Nv+1,P[i].v)-av;
}

void make_block(){
	int blcsiz=(int)sqrt(n+0.5);
	build(1,Nv);
	for(int i=1;i<=n;i++)
		belong[i]=(i-1)/blcsiz+1;
	cntB=(n-1)/blcsiz+1;
	for(int i=1;i<=n;i++) B[belong[i]].add_node(P[i]);
	B[1].mem_begin=tot+2;
	B[1].num=1;
	for(int i=2;i<=cntB;i++)
		B[i].mem_begin=B[i-1].mem_begin+Maxb*25,B[i].num=B[i-1].num+1;
	for(int i=1;i<=cntB;i++) B[i].init();
}

void solve(){
	X[0]=-INF; X[n+1]=INF;
	for(int i=1;i<=m;i++){
		if(A[i].type)
			query(A[i].x0,A[i].y0,A[i].x1,A[i].y1,A[i].k);
		else if(A[i].x0!=A[i].y0){
			int x=rank[A[i].x0],xb=bein[A[i].x0];
			int y=rank[A[i].y0],yb=bein[A[i].y0];
			swap(B[xb].P[x].v,B[yb].P[y].v);
			B[xb].make_tree();
			if(xb!=yb) B[yb].make_tree();
		}
	}
}

int main(){
	freopen("nt2012_attack.in","r",stdin);
	freopen("nt2012_attack.out","w",stdout);
	init();
	make_block();
	solve();
	return 0;
}