제출 #211783

#제출 시각아이디문제언어결과실행 시간메모리
211783zscoder청소 (JOI20_sweeping)C++17
100 / 100
4813 ms350216 KiB
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

using namespace std;
using namespace __gnu_pbds;
 
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define fbo find_by_order
#define ook order_of_key
 
typedef long long ll;
typedef pair<int,int> ii;
typedef vector<int> vi;
typedef long double ld; 
typedef tree<ll, null_type, less<ll>, rb_tree_tag, tree_order_statistics_node_update> pbds;

vector<ii> pt;

struct query
{
	int ty,val,id;
	query(int _ty=0,int _val=0,int _id=0): ty(_ty),val(_val),id(_id){}
};

int par[3333333];

struct DSU
{
	vi val;
	vector<vi> pset;
	void init()
	{
		val.clear(); pset.clear();
	}
	int add(int v, int id) //v = coordinate, id = id of point
	{
		int newid = val.size();
		val.pb(v); pset.pb({});
		if(id>=0)
		{
			par[id]=newid; //change the parent x or y of the point
			pset[newid].pb(id);
		}
		return newid;
	}
	int merge(int x, int y)
	{
		if(x==y) return x;
		if(pset[x].size()<pset[y].size()) swap(x,y);
		val[x]=max(val[x],val[y]);
		for(int z:pset[y]) 
		{
			par[z]=x; pset[x].pb(z);
		}
		return x;
	}
};

vector<query> queries;
ii ans[1111111];
int n,m,q;
DSU dsu;

ii getcoord(int id) //get coordinates of the point id
{
	//cerr<<id<<' '<<dsu.val.size()<<' '<<par[id*2]<<' '<<par[id*2+1]<<'\n';
	return {dsu.val[par[id*2]],dsu.val[par[id*2+1]]};
}

bool pushed[2222222];

void solve(int x, int y, vector<query> Q)
{
	if(Q.empty()) return ;
	/*
	cerr<<"SOLVE "<<x<<' '<<y<<'\n';
	cerr<<"QUERIES: \n";
	for(query qq:Q)
	{
		cerr<<qq.ty<<' '<<qq.val<<' '<<qq.id<<'\n';
	}
	*/
	if(x+y==n)
	{
		for(auto qry:Q)
		{
			if(qry.ty==1) ans[qry.id]=pt[qry.val];
		}
		return ;
	}
	dsu.init();
	int X = x+(n-x-y)/2+1; int Y = n+1-X; //X+Y=N+1 
	//cerr<<X<<' '<<Y<<'\n';
	vector<query> up,right;
	priority_queue<ii,vector<ii>,greater<ii> > xcoord,ycoord;
	for(auto qry:Q)
	{
		//cerr<<qry.ty<<' '<<qry.val<<' '<<qry.id<<' '<<pt.size()<<'\n';
		//cerr<<dsu.val.size()<<'\n';
		if(qry.ty==1)
		{
			int ptid = qry.val;
			if(pt[ptid].fi>=X) right.pb(qry);
			else if(pt[ptid].se>=Y) up.pb(qry);
			else
			{
				//cerr<<"QUERY OF ID "<<qry.id<<" HAS BEEN ANSWERED\n";
				ans[qry.id]=getcoord(ptid);
			}
		}
		else if(qry.ty==2)
		{
			//horizontal motion
			int L = qry.val;
			if(L>=Y) //everything in range with x < n-l gets swept to the right. note that n-L<=n-Y is still in the range, so our points don't get pushed outside the box yet
			{
				int newx = n-L;
				int curid = dsu.add(newx,-1);
				while(!xcoord.empty())
				{
					int tpx = xcoord.top().fi;
					if(tpx>=n-L) break;
					curid=dsu.merge(curid,xcoord.top().se);
					xcoord.pop();
				}
				xcoord.push({newx,curid});
				up.pb(qry);
			}
			else
			{
				//ycoord<=L suffer
				while(!ycoord.empty())
				{
					int tpy = ycoord.top().fi;
					if(tpy>L) break;
					int dsuid = ycoord.top().se; ycoord.pop();
					//for all the points with this coordinate
					for(int p:dsu.pset[dsuid]) //a point gets traversed at most log (M+Q) times here and under log N recursive calls
					{
						p/=2;
						if(!pushed[p])
						{
							pt[p] = getcoord(p);
							pt[p].fi = n-L;
							right.pb(query(4,p,-1)); //new point position later
							pushed[p]=1;
						}
					}
				}
				right.pb(qry);
			}
		}
		else if(qry.ty==3)
		{
			int L = qry.val;
			if(L>=X) 
			{
				int newy = n-L;
				int curid = dsu.add(newy,-1);
				while(!ycoord.empty())
				{
					int tpy = ycoord.top().fi;
					if(tpy>=n-L) break;
					curid=dsu.merge(curid,ycoord.top().se);
					ycoord.pop();
				}
				ycoord.push({newy,curid});
				right.pb(qry);
			}
			else
			{
				while(!xcoord.empty())
				{
					int tpx = xcoord.top().fi;
					//cerr<<tpx<<'\n';
					if(tpx>L) break;
					int dsuid = xcoord.top().se; xcoord.pop();
					//for all the points with this coordinate
					for(int p:dsu.pset[dsuid]) //a point gets traversed at most log (M+Q) times here and under log N recursive calls
					{
						p/=2;
						if(!pushed[p])
						{
							pt[p] = getcoord(p);
							pt[p].se = n-L;
							//cerr<<pt[p].fi<<' '<<pt[p].se<<'\n';
							up.pb(query(4,p,-1)); //new point position later
							pushed[p]=1;
						}
					}
				}
				up.pb(qry);
			}
		}
		else
		{
			int ptid = qry.val;
			pushed[ptid]=0; //reset point
			int x = pt[ptid].fi; int y = pt[ptid].se;
			if(y>=Y){pushed[ptid]=1; up.pb(qry);}
			else if(x>=X){pushed[ptid]=1; right.pb(qry);}
			//the point belongs here 
			else
			{
				int xid = dsu.add(x,2*ptid);
				int yid = dsu.add(y,2*ptid+1);
				xcoord.push({x,xid});
				ycoord.push({y,yid});
			}
		}
	}
	solve(X,y,right); solve(x,Y,up);
}

int main()
{
	ios_base::sync_with_stdio(0); cin.tie(0);
	cin>>n>>m>>q;
	vi T;
	for(int i=0;i<m;i++)
	{
		int x,y; cin>>x>>y;
		pt.pb({x,y}); T.pb(0);
		queries.pb(query(4,i,-1));
	}
	for(int i=0;i<q;i++)
	{
		int t; cin>>t;
		if(t==4)
		{
			int x,y; cin>>x>>y;
			queries.pb(query(4,pt.size(),-1));
			pt.pb({x,y});
			continue;
		}
		int val; cin>>val;
		if(t==1) val--;
		queries.pb(query(t,val,i));
	}
	for(int i=0;i<q;i++) ans[i]={-1,-1};
	solve(0,0,queries);
	for(int i=0;i<q;i++)
	{
		if(ans[i].fi>=0) cout<<ans[i].fi<<' '<<ans[i].se<<'\n';
	}
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...