• BZOJ2674 Attack


    题意

    题目链接
    简洁版:平面上有(n)个点,每个点有一个权值,有(m)个操作

    • 交换两点的权值
    • 询问一个矩形区域内第(k)小的权值

    (n<=60000,m<=10000)

    思路

    如果不是一个平面,而是一个序列,那就是一个动态区间第K大的问题,用整体二分即可解决
    于是我们在这道题上线套一个整体二分,然后问题转化为如何支持高速修改与查询一个矩形区域中点的个数
    不难想到用树套树进行解决。在这里我第一维(x坐标)采用的是线段树,第二维(y坐标)采用的是SBT
    (当然,大多数大佬使用的线段树套树状数组当然更为简单)
    时间复杂度(O(nlog^3n))
    另外不要忘了离散化

    注意事项

    • 数组大小一定要好好计算,稍不注意就会爆
    • 清空树套树与平常的不太相同,我是把线段树每一节点对应的SBT根给清掉

    code(有点长)

    #include<bits/stdc++.h>
    using namespace std;
    const int N=60005;
    const int M=10005;
    int n,m,cnt,t1,t2,mn=1e9,mx,hh;
    int tmp,val[N],ans[M];
    struct node{int _x1,_y1,_x2,_y2,z,id,k,tp;}a[N+(M<<2)],q1[N+(M<<2)],q2[N+(M<<2)];
    struct lsh{int nm,id,as;}xx[N+(M<<1)],yy[N+(M<<1)];
    inline int read()
    {
    	int s=0,w=1; char ch=getchar();
    	for(;!isdigit(ch);ch=getchar())if(ch=='-')w=-1;
    	for(;isdigit(ch);ch=getchar())s=(s<<1)+(s<<3)+(ch^48);
    	return s*w;
    }
    inline bool cmp(lsh x,lsh y){return x.nm<y.nm;}
    inline bool cmp1(lsh x,lsh y){return x.id<y.id;}
    inline void pre()
    {
    	sort(xx+1,xx+tmp+1,cmp);
    	sort(yy+1,yy+tmp+1,cmp);
    	for(int i=1;i<=tmp;++i)
    	{
    		if(i==1||xx[i].nm!=xx[i-1].nm) xx[i].as=++t1;
    		else xx[i].as=t1;
    		if(i==1||yy[i].nm!=yy[i-1].nm) yy[i].as=++t2;
    		else yy[i].as=t2;
    	}
    	sort(xx+1,xx+tmp+1,cmp1);
    	sort(yy+1,yy+tmp+1,cmp1);
    	for(int i=1;i<=n;++i)a[i]._x1=xx[i].as,a[i]._y1=yy[i].as;
    	for(int i=n+1,j=n+1;i<=cnt;++i)
    		if(!a[i].tp)
    		{
    			a[i]._x1=xx[j].as,a[i]._y1=yy[j++].as;
    			a[i]._x2=xx[j].as,a[i]._y2=yy[j++].as;
    		}
    		else
    		{
    			for(int e=i;e<=i+3;++e)
    				a[e]._x1=a[a[e].id]._x1,a[e]._y1=a[a[e].id]._y1;
    			++i,++i,++i;
    		}
    }
    struct SBT{
    	int rt[(N+M<<1)<<2],siz[N<<4],rp[N<<4],tot=0;
    	int lc[N<<4],rc[N<<4],rsiz[N<<4],vv[N<<4];
    	const double alpha=0.55;
    	inline int new_node(int v)
    	{
    		int num=++tot;lc[num]=rc[num]=0;
    		siz[num]=rsiz[num]=rp[num]=1;vv[num]=v;//新建节点必须初始化
    		return num;
    	}
    	inline void upt(int x)
    	{
    		siz[x]=siz[lc[x]]+siz[rc[x]]+rp[x];
    		rsiz[x]=rsiz[lc[x]]+rsiz[rc[x]]+1;
    	}
    	inline void zig(int &u)
    	{
    		int v=lc[u];lc[u]=rc[v];rc[v]=u;
    		upt(u);upt(v);u=v;
    	}
    	inline void zag(int &u)
    	{
    		int v=rc[u];rc[u]=lc[v];lc[v]=u;
    		upt(u);upt(v);u=v;
    	}
    	void ins(int &now,int p)
    	{
    		if(!now){now=new_node(p);return;}
    		++siz[now];
    		if(p==vv[now])++rp[now];
    		else if(p<vv[now])
    		{
    			ins(lc[now],p);
    			if(rsiz[lc[now]]>rsiz[now]*alpha) zig(now);
    		}
    		else
    		{
    			ins(rc[now],p);
    			if(rsiz[rc[now]]>rsiz[now]*alpha) zag(now);
    		}
    		upt(now);
    	}
    	void del(int &now,int p)
    	{
    		if(!now) return;
    		if(vv[now]==p)
    		{
    			if(rp[now]>1) --rp[now],--siz[now];
    			else if(!lc[now]||!rc[now]) now=lc[now]|rc[now];
    			else if(rsiz[lc[now]]>rsiz[rc[now]]) zig(now),del(now,p);
    			else zag(now),del(now,p);
    			if(now) upt(now);
    			return;
    		}
    		if(p<vv[now]) del(lc[now],p);
    		else del(rc[now],p);
    		upt(now);
    	}
    	int rank(int now,int p)
    	{
    		if(!now) return 0;
    		if(vv[now]==p) return siz[lc[now]]+rp[now];
    		else if(p<vv[now]) return rank(lc[now],p);
    		else return rank(rc[now],p)+siz[lc[now]]+rp[now];
    	}
    	inline int range(int now,int l,int r){return rank(now,r)-rank(now,l-1);}
    }sbt;
    struct Seg_tree{
    	void update(int rt,int l,int r,int p1,int p2,int v)
    	{
    		if(v>0)sbt.ins(sbt.rt[rt],p2);
    		else sbt.del(sbt.rt[rt],p2);
    		if(l>=r) return;
    		int mid=l+r>>1;
    		if(p1<=mid) update(rt<<1,l,mid,p1,p2,v);
    		else update(rt<<1|1,mid+1,r,p1,p2,v);
    	}
    	int query(int rt,int l,int r,int px1,int py1,int px2,int py2)
    	{
    		if(px1<=l&&r<=px2) return sbt.range(sbt.rt[rt],py1,py2);
    		int mid=l+r>>1,anss=0;
    		if(px1<=mid) anss+=query(rt<<1,l,mid,px1,py1,px2,py2);
    		if(mid<px2) anss+=query(rt<<1|1,mid+1,r,px1,py1,px2,py2);
    		return anss;
    	}
    	void clean(int rt,int l,int r,int p)
    	{
    		sbt.rt[rt]=0;
    		if(l>=r)return;
    		int mid=l+r>>1;
    		if(p<=mid) clean(rt<<1,l,mid,p);
    		else clean(rt<<1|1,mid+1,r,p);
    	}
    }T;
    void solve(int L,int R,int l,int r)
    {
    	if(l>r) return;
    	if(L==R)
    	{
    		for(int i=l;i<=r;++i)
    			if(!a[i].tp) ans[a[i].id]=L;
    		return;
    	}
    	int mid=L+R>>1,cnt1=0,cnt2=0;
    	for(int i=l;i<=r;++i)
    	{
    		if(a[i].tp)
    		{
    			if(a[i].z<=mid) T.update(1,1,t1,a[i]._x1,a[i]._y1,a[i].k),q1[++cnt1]=a[i];
    			else q2[++cnt2]=a[i];
    		}
    		else
    		{
    			int xk=T.query(1,1,t1,a[i]._x1,a[i]._y1,a[i]._x2,a[i]._y2);
    			if(a[i].k<=xk) q1[++cnt1]=a[i];
    			else q2[++cnt2]=a[i],q2[cnt2].k-=xk;
    		}
    	}
    	sbt.tot=0;
    	for(int i=l;i<=r;++i)
    		if(a[i].tp&&a[i].z<=mid) T.clean(1,1,t1,a[i]._x1);
    	for(int i=l;i<=l+cnt1-1;++i)a[i]=q1[i-l+1];
    	for(int i=l+cnt1;i<=r;++i)a[i]=q2[i-l-cnt1+1];
    	solve(L,mid,l,l+cnt1-1);
    	solve(mid+1,R,l+cnt1,r);
    }
    int main()
    {
    	n=read(),m=read();cnt=n;
    	for(int i=1;i<=n;++i)
    	{
    		int xi=read(),yi=read(),zi=read();
    		a[i]=node{xi,yi,0,0,zi,i,1,1};
    		xx[++tmp]=lsh{xi,i},yy[tmp]=lsh{yi,i};val[i]=zi;
    		mx=max(mx,zi),mn=min(mn,zi);
    	}
    	char opt[10];
    	for(int i=1;i<=m;++i)
    	{
    		scanf("%s",opt);
    		if(opt[0]=='Q')
    		{
    			int xx1=read(),yy1=read(),xx2=read(),yy2=read(),kk=read();
    			if(xx1>xx2) swap(xx1,xx2);
    			if(yy1>yy2) swap(yy1,yy2);
    			a[++cnt]=node{xx1,yy1,xx2,yy2,0,++hh,kk,0};
    			xx[++tmp]=lsh{xx1,tmp},yy[tmp]=lsh{yy1,tmp};
    			xx[++tmp]=lsh{xx2,tmp},yy[tmp]=lsh{yy2,tmp};
    		}
    		else
    		{
    			int _x=read()+1,_y=read()+1;
    			if(_x==_y) continue;
    			a[++cnt]=node{a[_x]._x1,a[_x]._y1,0,0,val[_x],_x,-1,1};
    			a[++cnt]=node{a[_x]._x1,a[_x]._y1,0,0,val[_y],_x,1,1};
    			a[++cnt]=node{a[_y]._x1,a[_y]._y1,0,0,val[_y],_y,-1,1};
    			a[++cnt]=node{a[_y]._x1,a[_y]._y1,0,0,val[_x],_y,1,1};
    			swap(val[_x],val[_y]);
    		}
    	}
    	while(a[cnt].tp==1) --cnt;
    	pre();
    	solve(mn,mx+1,1,cnt);
    	for(int i=1;i<=hh;++i)
    	{
    		if(ans[i]>mx) puts("It doesn't exist.");
    		else printf("%d
    ",ans[i]);
    	}
    	return 0;
    }
    
  • 相关阅读:
    流水账
    还是有希望啊
    The Java Tutorials:Collections
    绘图框架新需求
    Fractal Tree扩展
    js获取字符串最后一个字符代码
    js保留小数点后N位的方法介绍
    JS 实现 ResizeBar,可拖动改变两个区域(带iframe)大小
    js获取浏览器高度和宽度值,尽量的考虑了多浏览器。
    jquery自动将form表单封装成json的具体实现
  • 原文地址:https://www.cnblogs.com/zmyzmy/p/12127809.html
Copyright © 2020-2023  润新知