zoukankan      html  css  js  c++  java
  • ! JOISC2020DAY1扫除

    问题拆解,好题&难题



    发现:每个点经历了一次修改后,若(x_i<x_j)(y_i>y_j)(貌似并没有用到?)

    考虑线段树分治:

    每个询问记录修改时间区间

    每个时间段的区间将询问的点按(x)(y)排序

    用动态开点线段树维护最大值算出每个修改的区间

    (H)操作,在长度小于(l)的区域,可能会被(V)操作扫走,所以每次(V)操作,将(n-l_v-1)以内的区域都与(l_v)(max),这样就可以把两种操作分开进行,修改答案

    加入点无影响

    时间复杂度(O(nlog_n^2))

    #include<bits/stdc++.h>
    using namespace std;
    inline int read(){
    	int x=0,f=1;char c=getchar();
    	while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
    	while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    	return f==1?x:-x;
    }
    #define pai pair<int,int>
    #define mp make_pair
    #define fi first
    #define se second
    #define pb push_back 
    #define vi vector<int> 
    const int N=1600004;
    int n,m,Q,qn,tim,tot;
    int a[N][3],b[N][3],c[N][2],ans[N][2];
    int t[N<<5],lc[N<<5],rc[N<<5],rt[2];
    vector<pai>mv[2];
    inline int newnode(){
    	++tot;
    	lc[tot]=rc[tot]=t[tot]=0;
    	return tot;
    }
    void modify(int &p,int l,int r,int ql,int qr,int k){
    	if(ql>qr||qr<0||ql>n)return;
    	if(!p)p=newnode();
    	if(ql<=l&&r<=qr){t[p]=max(t[p],k);return;}
    	int mid=l+r>>1;
    	if(ql<=mid)modify(lc[p],l,mid,ql,qr,k);
    	if(mid<qr)modify(rc[p],mid+1,r,ql,qr,k);
    }
    int query(int p,int l,int r,int x){
    	if(!p)return 0;
    	if(l==r)return t[p];
    	int mid=l+r>>1;
    	if(x<=mid)return max(t[p],query(lc[p],l,mid,x));
    	else return max(t[p],query(rc[p],mid+1,r,x));
    }
    inline void mdf(int op,int len){//找每次操作可以修改的区域 
    	int t=query(rt[op^1],0,n,len);
    	mv[op].pb(mp(len,t));
    	modify(rt[op],0,n,t,n-len-1,len+1);
    }
    inline bool cmp0(int x,int y){
    	return ans[x][1]>ans[y][1];
    }
    inline bool cmp1(int x,int y){
    	return ans[x][0]>ans[y][0];
    }
    inline void solve(int l,int r,vi w){
    	if(l>r)return;
    	vi lw,rw,tmp;
    	int mid=l+r>>1,ql,qr,j,x,y;
    	for(auto i:w){
    		ql=b[i][1];qr=b[i][2];
    		if(ql<=l&&r<=qr)tmp.pb(i);
    		else{
    			if(ql<=mid)lw.pb(i);
    			if(mid<qr)rw.pb(i);
    		}
    	}
    	rt[0]=rt[1]=tot=0;
    	mv[0].clear();mv[1].clear();
    	for(int i=l;i<=r;i++)mdf(c[i][0],c[i][1]);
    	sort(tmp.begin(),tmp.end(),cmp0);
    	sort(mv[0].begin(),mv[0].end(),greater<pai>());
    	rt[0]=tot=j=0;
    	for(auto i:tmp){
    		x=ans[i][0];y=ans[i][1];
    		for(;j<mv[0].size()&&mv[0][j].fi>=y;j++){
    			modify(rt[0],0,n,mv[0][j].se,n-mv[0][j].fi,n-mv[0][j].fi);
    		}
    		ans[i][0]=max(x,query(rt[0],0,n,x));
    	}
    	sort(tmp.begin(),tmp.end(),cmp1);
    	sort(mv[1].begin(),mv[1].end(),greater<pai>());
    	rt[1]=tot=j=0;
    	for(auto i:tmp){
    		x=ans[i][0];y=ans[i][1];
    		for(;j<mv[1].size()&&mv[1][j].fi>=x;j++){
    			modify(rt[1],0,n,mv[1][j].se,n-mv[1][j].fi,n-mv[1][j].fi);
    		}
    		ans[i][1]=max(y,query(rt[1],0,n,y));
    	}
    	if(l==r)return;
    	solve(l,mid,lw);solve(mid+1,r,rw);
    }
    int main(){
    	n=read();m=read();Q=read();
    	for(int i=1;i<=m;i++){
    		a[i][0]=read();a[i][1]=read();
    		a[i][2]=1;
    	}
    	for(int i=1,op,x;i<=Q;i++){
    		op=read();
    		if(op==1){
    			b[++qn][0]=x=read();b[qn][1]=a[x][2];
    			b[qn][2]=tim;
    		} 
    		else if(op==2){
    			c[++tim][1]=read();
    		}
    		else if(op==3){
    			c[++tim][0]=1;c[tim][1]=read();
    		}
    		else{
    			a[++m][0]=read();a[m][1]=read();
    			a[m][2]=tim+1;
    		}
    	}
    	vi vec;
    	for(int i=1,x;i<=qn;i++){
    		x=b[i][0];
    		ans[i][0]=a[x][0];ans[i][1]=a[x][1];
    		if(b[i][1]<=b[i][2])vec.pb(i); 
    	}
    	solve(1,tim,vec);
    	for(int i=1;i<=qn;i++)
    		cout<<ans[i][0]<<" "<<ans[i][1]<<"
    ";
    	return (0-0);
    }
    
  • 相关阅读:
    MongoDB数据创建与使用
    python库安装方法及下载依赖库
    java开发基础知识学习
    wifi破解基础及工具的使用
    Markdonw基本语法学习
    toj 4353 Estimation(树状数组+二分查找)
    POJ 1694 An Old Stone Game【递归+排序】
    POJ 2092 Grandpa is Famous【水---找出现第二多的数】
    POJ 2993 Emag eht htiw Em Pleh【模拟画棋盘】
    POJ 1068 Parencodings【水模拟--数括号】
  • 原文地址:https://www.cnblogs.com/aurora2004/p/12552296.html
Copyright © 2011-2022 走看看