pbds大法爆零求hack
查看原帖
pbds大法爆零求hack
777809
IOI_AK_TLR楼主2024/9/8 08:44
#include <bits/stdc++.h>
#include <bits/extc++.h>
using namespace std;
using namespace __gnu_pbds;
const int Max=1e5+10;
int n,m,u,v,ans;
/*
维护一个平衡树:每个监控的信息,按照时间t排序
*/
tree<pair<int,int>,null_type,less<pair<int,int>>,rb_tree_tag,tree_order_statistics_node_update> tr;
/*
另一棵平衡树:相邻(时间)的两个监控这个入通过的速度
下面的列表是用监控标号对应速度 ds[i]表示时间排名i监控和时间排名i+1监控之间这个入通过的速度
*/
tree<pair<int,int>,null_type,greater<pair<int,int>>,rb_tree_tag,tree_order_statistics_node_update> dif;
int ds[Max];
struct InpD{
	int x,t;
}inp[Max];
int main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		cin>>inp[i].x>>inp[i].t;
		tr.insert(pair<int,int>(inp[i].t,inp[i].x));
	}
//	cerr<<"--------debug--------\n";
	for(int i=1;i<n;i++){
		pair<int,int> tmp(abs(tr.find_by_order(i)->second-tr.find_by_order(i-1)->second)/abs(tr.find_by_order(i)->first-tr.find_by_order(i-1)->first),i-1);
		ds[i-1]=tmp.first;
		dif.insert(tmp);
//		cout<<tmp.first<<" ";
	}
//	cerr<<"\n-------\n";
	for(int i=1;i<=m;i++){
		ans=0;
		cin>>u>>v;
		pair<int,int> old(inp[u].t,inp[u].x);
		pair<int,int> ins(v,inp[u].x);
		pair<int,int> tmp1(ds[tr.order_of_key(pair<int,int>(inp[u].t,inp[u].x))],tr.order_of_key(pair<int,int>(inp[u].t,inp[u].x)));  //要改动的点和下一个点之间的数据
		pair<int,int> lst;
		if(tr.order_of_key(pair<int,int>(inp[u].t,inp[u].x))-1!=-1)
			lst=*tr.find_by_order(tr.order_of_key(pair<int,int>(inp[u].t,inp[u].x))-1);
		pair<int,int> tmp2(ds[tr.order_of_key(pair<int,int>(lst.first,lst.second))],tr.order_of_key(lst)); //要改动的点和上一个点的数据
		pair<int,int> tmp3;//要改动的点上一个点到要改动的点的下一个点的数据
//		cerr<<"------debug------   "<<tmp1.first<<" "<<tmp1.second<<"\n";
		int ttm1=tr.order_of_key(pair<int,int>(inp[u].t,inp[u].x));	//u的排名
		pair<int,int> oldnxt,oldfrt;
		if(ttm1!=0){
			oldfrt=*(tr.find_by_order(ttm1-1));
		}
		if(ttm1!=n-1){
			oldnxt=*(tr.find_by_order(ttm1+1));
		}
		/*
		如若被改动的点改动到了一个与之前毫不相关的时间点(即已经不再以前的之前和之后的点的时间之间)
		那么应该考虑tmp3的速度?事实上确实需要
		*/
		if(ttm1!=0&&ttm1!=n-1){
			tmp3=pair<int,int>(abs(tr.find_by_order(ttm1+1)->second-tr.find_by_order(ttm1-1)->second)/abs(tr.find_by_order(ttm1+1)->first-tr.find_by_order(ttm1-1)->first),-114514);
		}
		tr.erase(tr.find_by_order(tr.order_of_key(old)));
		tr.insert(ins);
		int ttm2=tr.order_of_key(ins);		//时间改成v以后得排名
		if(ttm1!=n-1){
			dif.erase(dif.find_by_order(dif.order_of_key(tmp1)));
		}	//要改动的点不是最后(时间最晚)的点
		if(ttm1!=0){
			dif.erase(dif.find_by_order(dif.order_of_key(tmp2)));
		}	//不是最早的
//		cerr<<"-----debug----- "<<tmp1.first<<" "<<tmp2.first<<endl;
		
		if(ttm1!=ttm2){
			dif.insert(tmp3);
		}	//需要考虑tmp3
		/*
		此时dif已经完毕
		原因是修改后的点速度一定大于等于之前那样的速度
		*/
		ans=max(ans,dif.find_by_order(0)->first);
		
		/*
		接下来 考虑修改后它与之前和之后的(时间)的点(即ins和其前与后)的速度
		*/
		
		pair<int,int> nwnxt,nwfrt;
		if(ttm2!=0){
			nwfrt=*(tr.find_by_order(ttm2-1));
			ans=max(ans,abs(nwfrt.second-ins.second)/abs(nwfrt.first-ins.first));
//			cerr<<"----dbg------"<<abs(nwfrt.second-ins.second)/abs(nwfrt.first-ins.first)<<endl;
		}
		if(ttm2!=n-1){
			nwnxt=*(tr.find_by_order(ttm2+1));
			ans=max(ans,abs(nwnxt.second-ins.second)/abs(nwnxt.first-ins.first));
		}
		
		/*
		还原
		*/
		tr.insert(old);
		tr.erase(tr.find_by_order(tr.order_of_key(ins)));
		if(ttm1!=n-1){
			dif.insert(tmp1);
		}	//要改动的点不是最后(时间最晚)的点
		if(ttm1!=0){
			dif.insert(tmp2);
		}	//不是最早的
		if(ttm1!=ttm2){
			dif.erase(dif.find_by_order(dif.order_of_key(tmp3)));
		}	//需要考虑tmp3
		
		cout<<ans<<'\n';
	}
	return 0;
}
2024/9/8 08:44
加载中...