zoukankan      html  css  js  c++  java
  • joisc 2020 扫除

    算法1:
    考虑没有插入操作怎么办。
    先考虑sub3。
    定义一个点在边界上:它的右上角没有任何点。
    注意到无论怎么进行操作,在边界的点还是会在边界,且顺序不会交换。
    所以可以用线段树二分简单维护。
    再考虑sub4。
    sub4和sub3的区别:在sub3中每个点都在边界上,但是sub4并不。
    但是注意到如果一个点在边界上,则它在之后的操作它还是在边界上。
    所以可以使用线段树+平衡树维护。
    开平衡树维护边界上的点的x/y坐标。
    不能用线段树,因为要支持插入操作。
    在修改时在平衡树二分+平衡树区间赋值维护。
    在操作时,可能有新的点到达边界。
    使用两个线段树找点即可。
    (这个部分还是不太懂)
    由于每个点会被插入到平衡树中至多1次,所以时间复杂度是(O(nlog_2 n))
    有插入操作时,注意到每个修改操作对答案的贡献是独立的,于是可以使用时间线段树规避删除。
    算法2:
    算法1太难写了,考虑一种更好写的算法。
    考虑sub2,没有向上推的操作。
    一个点的y坐标不会变,维护个关于x坐标的线段树即可。
    拓展到sub4。
    直接拓展会有一个问题。
    一个操作相当于把区间([1,r])的点在线段树上坐标对(n-r)(max)
    然而操作的范围不一定是([1,n-r])
    比如我们要向上推。但是有一个比较小,但是距离特别长的向右推的操作把部分灰尘推走了。
    所以一个操作的是把区间([x,r])的点的坐标对(n-r)取max。
    我们要得到这个x。
    维护两个线段树,维护(x,y)轴的答案。
    按照顺序执行所有修改操作。
    对于一个修改操作, 把对应的区间对(len)取max。然后单点查询另一颗线段树在len位置的值。
    画图可以知道正确性。
    在查询操作时,由于一个推距离(=x)的点只能影响到某个坐标(<=x)的点,所以把所有点按照坐标从大到小排序然后分两维做。
    有插入操作时也可以时间线段树。

    #include<bits/stdc++.h>
    using namespace std;
    #define N 1000010
    int n,m,q,x[N],y[N],ql[N],qr[N],ct,cc,le[N],tp[N],ax[N],ay[N],t[N];
    struct no{
    	int x,y;
    };
    vector<int>v[N*4];
    vector<no>op[2];
    int operator <(no x,no y){
    	return x.x>y.x||(x.x==y.x&&x.y>y.y);
    }
    int mx[N*40],cv,lc[N*40],rc[N*40],rt[2];
    void up(int &o,int l,int r,int x,int y,int z){
    	if(!o)
    		o=++cv;
    	if(r<x||y<l)
    		return;
    	if(x<=l&&r<=y){
    		mx[o]=max(mx[o],z);
    		return;
    	}
    	int md=(l+r)/2;
    	up(lc[o],l,md,x,y,z);
    	up(rc[o],md+1,r,x,y,z);
    }
    int qu(int o,int l,int r,int x){	
    	if(l==r)
    		return mx[o];
    	int md=(l+r)/2;
    	if(x<=md)
    		return max(qu(lc[o],l,md,x),mx[o]);
    	return max(qu(rc[o],md+1,r,x),mx[o]);
    }
    int cx(int x,int y){
    	return ax[x]>ax[y];
    }
    int cy(int x,int y){
    	return ay[x]>ay[y];
    }
    void ins(int o,int l,int r,int x,int y,int z){
    	if(r<x||y<l)
    		return;
    	if(x<=l&&r<=y){
    		v[o].push_back(z);
    		return;
    	}
    	int md=(l+r)/2;
    	ins(o*2,l,md,x,y,z);
    	ins(o*2+1,md+1,r,x,y,z);
    }
    void cl(){
    	for(int i=1;i<=cv;i++)
    		lc[i]=rc[i]=mx[i]=0;
    	rt[0]=rt[1]=cv=0;
    }
    void fz(int o,int l,int r){
    	op[0].clear();
    	op[1].clear();
    	cl();
    	for(int i=l;i<=r;i++){
    		int va=qu(rt[tp[i]^1],0,n,le[i]);
    		op[tp[i]].push_back((no){le[i],va});
    		up(rt[tp[i]],0,n,va,n-le[i]-1,le[i]+1);
    	}
    	cl();
    	sort(op[0].begin(),op[0].end());
    	sort(op[1].begin(),op[1].end());
    	sort(v[o].begin(),v[o].end(),cy);
    	int j=0;
    	for(int x:v[o]){
    		while(j<op[0].size()&&op[0][j].x>=ay[x]){
    			up(rt[0],0,n,op[0][j].y,n-op[0][j].x,n-op[0][j].x);
    			j++;
    		}
    		ax[x]=max(ax[x],qu(rt[0],0,n,ax[x]));
    	}
    	sort(v[o].begin(),v[o].end(),cx);
    	j=0;
    	for(int x:v[o]){
    		while(j<op[1].size()&&op[1][j].x>=ax[x]){
    			up(rt[1],0,n,op[1][j].y,n-op[1][j].x,n-op[1][j].x);
    			j++;
    		}
    		ay[x]=max(ay[x],qu(rt[1],0,n,ay[x]));
    	}
    	int md=(l+r)/2;
    	if(l>=r)return;
    	fz(o*2,l,md);
    	fz(o*2+1,md+1,r);
    }
    int main(){
    	scanf("%d%d%d",&n,&m,&q);
    	for(int i=1;i<=m;i++){
    		scanf("%d%d",&x[i],&y[i]);
    		t[i]=1;
    	}
    	for(int i=1;i<=q;i++){
    		int op;
    		scanf("%d",&op);
    		if(op==1){
    			int p;
    			scanf("%d",&p);
    			ax[++cc]=x[p];
    			ay[cc]=y[p];
    			qr[cc]=ct;
    			ql[cc]=t[p];
    		}
    		if(op==2){
    			int x;
    			scanf("%d",&x);
    			le[++ct]=x;
    			tp[ct]=0;
    		}
    		if(op==3){
    			int x;
    			scanf("%d",&x);
    			le[++ct]=x;
    			tp[ct]=1;
    		}
    		if(op==4){
    			int a,b;
    			scanf("%d%d",&a,&b);
    			x[++m]=a;
    			y[m]=b;
    			t[m]=ct+1;
    		}
    	}
    	for(int i=1;i<=cc;i++)
    		ins(1,1,ct,ql[i],qr[i],i);
    	fz(1,1,ct);
    	for(int i=1;i<=cc;i++)
    		printf("%d %d
    ",ax[i],ay[i]);
    }
    
  • 相关阅读:
    Processing中PImage类和loadImage()、createImage()函数的相关解析
    基于Maxmspjitter的基础【pixel shader】绘制模板Patcher
    Processing多窗口程序范例(三)
    SpringBoot:基于注解的@CachePut
    Android开发—错误记录1:W/System.err: java.net.ConnectException: Connection refused
    自控力第一章-我要做,我不要,我想要:什么是意志力?为什么意志力至关重要
    超算结课小结
    linpack_2
    搭建Linpack
    汇编程序返回dos
  • 原文地址:https://www.cnblogs.com/ctmlpfs/p/13858306.html
Copyright © 2011-2022 走看看