并查集T飞了
查看原帖
并查集T飞了
241838
microchip楼主2024/6/5 15:13

RT,用的可持久化并查集做的,虽然用了vector和class,但复杂度感觉没问题,不至于第五个样例要跑好几个小时吧

#include<bits/stdc++.h>
using namespace std;

inline int read(){
	int n=0,f=1;
	char c=getchar();
	while(c<'0' || c>'9'){
		if(c=='-') f=-1;
		c=getchar();
	}
	while(c>='0' && c<='9'){
		n=(n<<3)+(n<<1)+(c^48);
		c=getchar();
	}
	return n*f;
}

inline void write(int x){
	if(x<0){
		putchar('-');
		x=-x;
	}
	if(x>9) write(x/10);
	putchar(x%10^48);
	return;
}

class Persistent_SegmentTree{
	private:
		struct node{
			int left,right,val;
		}Tree[4000050];
		int len,root[200050],nth,kth;
	public:
		void build_tree(int &no,int l,int r,int num[]){
			if(no==0)no=++nth;
			if(l==r){
				Tree[no].val=num[l];
				return;
			}int mid=(l+r)/2;
			build_tree(Tree[no].left,l,mid,num);
			build_tree(Tree[no].right,mid+1,r,num);
		}
		void build(int num[],int L){
			memset(Tree,0,sizeof(Tree));
			len=L;nth=0;kth=0;
			root[0]=0;
			build_tree(root[0],1,len,num);
		}void add(int &no,int l,int r,int Loc,int val){
			if(l==r){
				Tree[nth].val=val;
				return;
			}int mid=(l+r)/2;
			if(mid>=Loc){
				Tree[nth].left=nth+1;
				Tree[nth].right=Tree[no].right;
				nth++;
				add(Tree[no].left,l,mid,Loc,val);
			}else{
				Tree[nth].left=Tree[no].left;
				Tree[nth].right=nth+1;
				nth++;
				add(Tree[no].right,mid+1,r,Loc,val);
			}
		}void change_val(int ver,int loc,int val){
			root[++kth]=++nth;
			add(root[ver],1,len,loc,val);
		}int get_val(int &no,int l,int r,int Loc){
			if(l==r)return Tree[no].val;
			int mid=(l+r)/2;
			if(mid>=Loc)return get_val(Tree[no].left,l,mid,Loc);
			else return get_val(Tree[no].right,mid+1,r,Loc);
		}int num_val(int ver,int loc){
			return get_val(root[ver],1,len,loc);
		}void cpy_ver(int ver){
			root[++kth]=root[ver];
		}
}T_f,T_s;

struct node{
	int to,val;
}N;

struct edge{
	int from,to,depth;
}ed[400050];

struct Dij{
	int no,val;
}tp;

bool operator<(const Dij &x,const Dij &y){
	return x.val>y.val;
}

bool cmp(edge x,edge y){
	return x.depth>y.depth;
}

int Tn,n,m,u,v,l,a,f[200050],siz[200050],deep[400050],version[400050],nth,ver,q,k,s,V,P,lastans,dist[200050],ans;
bool flag[200050];
vector<node> T[200050];
priority_queue<Dij> Q;

int find(int x){
	int fa=T_f.num_val(ver,x);
	if(fa==x)return x;
	return find(fa);
}

void merge(int x,int y){
	int fa_x=find(x);
	int fa_y=find(y);
	if(fa_x==fa_y)return;
	T_f.change_val(ver,fa_x,fa_y);
	T_s.change_val(ver,fa_y,T_s.num_val(ver,fa_x)+T_s.num_val(ver,fa_y));
}

int main()
{
//	freopen("input.txt","r",stdin);
//	freopen("output.txt","w",stdout);
	for(int i=0;i<200050;i++)f[i]=i,siz[i]=1;
	Tn=read();
	while(Tn--){
		lastans=0;nth=0;ver=0;
		memset(flag,0,sizeof(flag));
		memset(deep,0,sizeof(deep));
		memset(version,0,sizeof(version));
		n=read();m=read();
		for(int i=1;i<=n;i++)T[i].clear();
		for(int i=1;i<=m;i++){
			u=read();v=read();l=read();a=read();
			N.to=v;N.val=l;
			T[u].push_back(N);
			N.to=u;
			T[v].push_back(N);
			ed[i].from=u;
			ed[i].to=v;
			ed[i].depth=a;
		}tp.no=1;tp.val=0;
		Q.push(tp);
		while(!Q.empty()){
			tp=Q.top();
			Q.pop();
			if(flag[tp.no]==0){
				flag[tp.no]=1;
				dist[tp.no]=tp.val;
				Dij tmp;
				for(unsigned int i=0;i<T[tp.no].size();i++){
					tmp.no=T[tp.no][i].to;
					tmp.val=T[tp.no][i].val+tp.val;
					Q.push(tmp);
				}
			}
		}sort(ed+1,ed+m+1,cmp);
		T_f.build(f,n);
		T_s.build(siz,n);
		for(int i=1;i<=m;i++){
			int x=ed[i].from,y=ed[i].to;
			if(T_s.num_val(ver,find(x))>T_s.num_val(ver,find(y)))swap(x,y);
			if(find(x)==find(y)){
				if(i==m||ed[i].depth!=ed[i+1].depth){
					nth++;
					deep[nth]=ed[i].depth;
					version[nth]=ver;
				}continue;
			}
			merge(x,y);
			ver++;
			if(i==m||ed[i].depth!=ed[i+1].depth){
				nth++;
				deep[nth]=ed[i].depth;
				version[nth]=ver;
			}
		}deep[0]=2147483647;
		version[0]=0;
		q=read();k=read();s=read();
		while(q--){
			ans=2147483647;
			V=read();P=read();
			V=(V+k*lastans-1)%n+1;
			P=(P+k*lastans)%(s+1);
			int L=0,R=nth+1,mid;
			while(L<R){
				mid=(L+R)/2;
				if(deep[mid]>P)L=mid+1;
				else R=mid;
			}L--;
			if(P==0)L=nth;
			ver=version[L];
			for(int i=1;i<=n;i++)
				if(find(i)==find(V))ans=min(ans,dist[i]);
			write(ans);
			puts("");
			lastans=ans;
		}
	}
	return 0;
}
2024/6/5 15:13
加载中...