THUWC2024 题解

t1-小 R 的项目

对于 \(n\) 个子集的 \(2^n\) 个子集,显然只有对这个子集和最大的人有用,所以 \(2^n \times m\) 找出这个人,然后 \(3^n\) 枚举子集合并。

t2-小 R 的序列

先考虑 \(m=1\) 怎么做,因为 \(m\neq 1\) 只需要对上一次的期望做相同的操作就行。

枚举随机到的长度 \(len\)\(i\) 变到的期望是所有包含 \(i\) 的长度为 \(len\) 的区间的和乘 \(\frac{1}{len}\)

这个不难写成一个矩阵的形式,这样就可以得到 \(n^3 log m\) 的做法。

观察一下发现这个矩阵的每一行都是由上一行移位得到的,所以只需要维护这个矩阵的第一行,这样就可以把矩阵乘法优化到 \(n^2 logm\)。但这是非常显然的卷积形式,使用 NTT 即可做到 \(nlognlogm\)

t4-小 C 的连廊

将每一行的联通块缩成一个点,相邻的块连一条边,设两个块相交部分 \(y\) 最小的位置的 \(y\)\(y1\),则边权为 \(\min(cnt_{x,y1},cnt_{x+1,y1})\)\(cnt_{i,j}\) 表示对 \((i,j)\) 这个点可以通过的最大风速。这样直接连边的数量是 \(O(q)\) 级别的。然后建立最大生成树,询问 \(x1,y1,x2,y2\) 的答案为 \(cnt_{x1,y1},cnt_{x2,y2}\) 还有这两个点所在联通块的最大生成树上路径上边权的最小值。这样这题就变成了动态维护最大生成树,使用LCT维护。

对第三档分,因为不会相交,所以直接维护 \(n\) 个 set 二分找到有交集的段然后暴力连边,细节不多。

对整道题虽然它会相交,相交的时候会发生变化的边数以及新连接的边数都是 \(O(q)\) 级别的,而且边权都是改大,不会出现一条边之前在生成树上,改之后不在的情况,所以同样直接 set 维护即可,只是细节很多。

代码(不保证是对的,能过小范围对拍与大样例)

#include<bits/stdc++.h>
#define sit set<node>::iterator
using namespace std;
const int inf=0x3f3f3f3f;
int n,m,q,tot;
struct node{
	int l,r,id;
	node(int l_,int r_,int id_){
		l=l_,r=r_,id=id_;
	}
	bool operator<(const node&x)const{
		return l<x.l;
	}
};
multiset<node>s[100005];
int w[1000005],X[1000005];
int dy[1000005],o[1000005],up[1000005],down[1000005];
int bel(int x,int y){
	sit it=s[x].upper_bound(node(y,0,0));
	if(it==s[x].begin())return -1;
	it--;
	if((*it).r>=y)return (*it).id;
	return -1;
}
struct edge{
	int x,y,z;
	edge(int x_,int y_,int z_){
		x=x_,y=y_,z=z_;
	}
	edge(){}
}e[1000005];
bool inc(int l1,int r1,int l2,int r2){
	return max(l1,l2)<=min(r1,r2);
}
struct LCT{
	int son[1000005][2],mn[1000005],lazy[1000005],fath[1000005],mnp[1000005];
	LCT(){
		memset(son,0,sizeof son);
		memset(mn,inf,sizeof mn);
		memset(lazy,0,sizeof lazy);
		memset(fath,0,sizeof fath);
		memset(mnp,0,sizeof mnp);
	}
	int gettype(int x){
		return son[fath[x]][1]==x;
	}
	void rev(int p){
		swap(son[p][0],son[p][1]); 
	}
	void pushup(int p){
		mn[p]=w[p],mnp[p]=p;
		if(mn[son[p][0]]<mn[p]){
			mn[p]=mn[son[p][0]];
			mnp[p]=mnp[son[p][0]];
		}
		if(mn[son[p][1]]<mn[p]){
			mn[p]=mn[son[p][1]];
			mnp[p]=mnp[son[p][1]];
		}
	}
	void pushdown(int p){
		if(lazy[p]){
			lazy[son[p][0]]^=1,lazy[son[p][1]]^=1;
			rev(son[p][0]),rev(son[p][1]);
			lazy[p]=0;
		}
	}
	bool isroot(int p){
		return son[fath[p]][0]!=p&&son[fath[p]][1]!=p;
	}
	void rotate(int x){
		int y=fath[x],z=fath[y],k=gettype(x);
		if(!isroot(y))son[z][gettype(y)]=x;
		son[y][k]=son[x][k^1],fath[son[y][k]]=y;
		son[x][k^1]=y,fath[y]=x,fath[x]=z;
		pushup(y),pushup(x);
	}
	void pd(int p){
		if(!isroot(p))pd(fath[p]);
		pushdown(p); 
	}
	void splay(int x){
		pd(x);
		while(!isroot(x)){
			int y=fath[x];
			if(!isroot(y)){
				if(gettype(x)!=gettype(y))rotate(x);
				else rotate(y);
			}
			rotate(x);
		}
	}
	void access(int x){
		for(int s=0;x;s=x,x=fath[x])splay(x),son[x][1]=s,pushup(x);
	}
	void makeroot(int x){
		access(x);
		splay(x);
		rev(x);
		lazy[x]^=1;
	}
	int findroot(int x){
		access(x);
		splay(x);
		while(son[x][0])x=son[x][0];
		splay(x);
		return x;
	}
	void split(int x,int y){
		makeroot(x);
		access(y);
		splay(y);
	}
	void link(int x,int y){
		makeroot(x);
		splay(x);
		fath[x]=y;
	}
	void cut(int x,int y){
		split(x,y);
		fath[x]=0;
		son[y][0]=0;
	}
	int Getmn(int x,int y){
		split(x,y);
		return mn[y];
	}
	int Getp(int x,int y){
		split(x,y);
		return mnp[y];
	}
	void update(int x,int val){
		splay(x);
		w[x]=val;
		pushup(x);
	}
}t;
void addedge(int x,int y,int z){
//	cout<<x<<" "<<y<<" "<<z<<endl;
	if(t.findroot(x)==t.findroot(y)){
		int v=t.Getmn(x,y);
		int pos=t.Getp(x,y);
		if(v>=z)return;
		t.cut(pos,e[pos].x);
		t.cut(pos,e[pos].y);
	}
	tot++;
	t.update(tot,z);
	t.link(tot,x);
	t.link(tot,y);
	o[tot]=1;
	e[tot]=edge(x,y,z);
}
void merge(int id,int l,int r,int p){
	if(l>r)return;
	sit it=s[id].lower_bound(node(l,0,0));
	if(it!=s[id].begin())it--;
	for(;it!=s[id].end();it++){
		if((*it).l>r)break;
		if(inc((*it).l,(*it).r,l,r)){
			int len=min(down[p],(*it).r)-max((*it).l,up[p]);
			addedge((*it).id,p,len);
		}
	}
}
set<node>del;
void upd_lr(int x,int l,int r,int &ll,int &rr){
	sit it=s[x].upper_bound(node(l,0,0));
	bool tg=0;
	if(it!=s[x].begin()){
		it--;
		tg=1;
	}
//	cout<<x<<" "<<l<<" "<<r<<":\n";
	sit it2=it;if(tg)it2++;
	if((l>(*it).r+1||!tg)&&(it2==s[x].end()||r<(*it2).l-1));
	else{
		if((*it).r>=r&&tg)return;
		if((*it).r>=l&&tg);
		else{
			if(tg){
				if((*it).r==l-1)ll=min(ll,(*it).l),rr=max(rr,(*it).r);//,cout<<(*it).l<<" "<<(*it).r<<" 1111\n";
				it++;
			}
		}
		for(;;it++){
			if(it==s[x].end()||(*it).l>r+1)break;
			ll=min(ll,(*it).l);
			rr=max(rr,(*it).r);
//			cout<<(*it).l<<" "<<(*it).r<<" 3333\n";
		}
	}
}
int main(){
//	system("fc a.out 3.ans /N");
	freopen("data.in","r",stdin);
	freopen("code.out","w",stdout);
//	freopen("3.in","r",stdin);
//	freopen("a.out","w",stdout);
	scanf("%d%d%d",&q,&n,&m);
	while(q--){
		int op;
		scanf("%d",&op);
		if(op==1){
			int x,l,r;
			scanf("%d%d%d",&x,&l,&r);
			tot++;
			int llt=tot;
			X[llt]=x;
			t.update(tot,inf);
			if(s[x].empty()){
				up[llt]=l,down[llt]=r;
				merge(x-1,l,r,llt);
				merge(x+1,l,r,llt);
				s[x].insert(node(l,r,llt));
				continue;
			}
			sit it=s[x].upper_bound(node(l,0,0));
			bool tg=0;
			if(it!=s[x].begin()){
				it--;
				tg=1;
			}
//			cout<<(it==s[x].end())<<" ";
			up[llt]=l,down[llt]=r;
			upd_lr(x,l,r,up[llt],down[llt]);
			sit it2=it;if(tg)it2++;
			if((l>(*it).r+1||!tg)&&(it2==s[x].end()||r<(*it2).l-1)){
//				cout<<x<<" "<<l<<" "<<r<<" 1111\n";
				merge(x-1,l,r,llt);
				merge(x+1,l,r,llt);
			}
			else{
				if((*it).r>=r&&tg)continue;
//				cout<<x<<" "<<l<<" "<<r<<" "<<(*it).l<<" "<<(*it).r<<" "<<tg<<":\n";
				if((*it).r>=l&&tg){
					addedge(llt,(*it).id,inf);
					int id=bel(x-1,(*it).r);
					if(id!=-1)addedge(id,llt,min(down[id],down[llt])-max(up[id],up[llt]));
					id=bel(x-1,l);
					if(id!=-1)addedge(id,llt,min(down[id],down[llt])-max(up[id],up[llt]));
					id=bel(x+1,(*it).r);
					if(id!=-1)addedge(id,llt,min(down[id],down[llt])-max(up[id],up[llt]));
					id=bel(x+1,l);
					if(id!=-1)addedge(id,llt,min(down[id],down[llt])-max(up[id],up[llt]));
					del.clear();
				}
				else{
					del.clear();
					if(tg){
						if((*it).r==l-1){
							int id=bel(x-1,l);
							if(id!=-1)addedge(id,llt,min(down[id],down[llt])-max(up[id],up[llt]));
							id=bel(x+1,l);
							if(id!=-1)addedge(id,llt,min(down[id],down[llt])-max(up[id],up[llt]));
							del.insert((*it));
							addedge(llt,(*it).id,inf);
						}
						it++;
					}
					if(it!=s[x].end()){
						int nxt=min((*it).l-1,r);
						merge(x-1,l,nxt,llt);
//						cout<<l<<" "<<(*it).l-1<<endl;
						int id=bel(x-1,nxt);
						if(id!=-1)addedge(id,llt,min(down[id],down[llt])-max(up[id],up[llt]));
						id=bel(x-1,l);
						if(id!=-1)addedge(id,llt,min(down[id],down[llt])-max(up[id],up[llt]));
						merge(x+1,l,nxt,llt);
						id=bel(x+1,nxt);
						if(id!=-1)addedge(id,llt,min(down[id],down[llt])-max(up[id],up[llt]));
						id=bel(x+1,l);
						if(id!=-1)addedge(id,llt,min(down[id],down[llt])-max(up[id],up[llt]));
//						del.insert((*it));
					}
				}
				for(;;it++){
					if(it==s[x].end()||(*it).l>r+1){
						it--;
						if((*it).r<=r){
//							cout<<(*it).r+1<<' '<<r<<endl;
							merge(x-1,(*it).r+1,r,llt);
							if((*it).r<r){
								int id=bel(x-1,(*it).r+1);
								if(id!=-1)addedge(id,llt,min(down[id],down[llt])-max(up[id],up[llt]));
							}
							merge(x+1,(*it).r+1,r,llt);
							int id=bel(x+1,(*it).r+1);
							if(id!=-1)addedge(id,llt,min(down[id],down[llt])-max(up[id],up[llt]));
						}
						break;
					}
					sit it1=it;it1++;
					if(it1!=s[x].end()&&(*it1).l-1<=r){
						merge(x-1,(*it).r+1,(*it1).l-1,llt);
						int id=bel(x-1,(*it).r+1);
						if(id!=-1)addedge(id,llt,min(down[id],down[llt])-max(up[id],up[llt]));
						id=bel(x-1,(*it1).l-1);
						if(id!=-1)addedge(id,llt,min(down[id],down[llt])-max(up[id],up[llt]));
						merge(x+1,(*it).r+1,(*it1).l-1,llt);
						id=bel(x+1,(*it).r+1);
						if(id!=-1)addedge(id,llt,min(down[id],down[llt])-max(up[id],up[llt]));
						id=bel(x+1,(*it1).l-1);
						if(id!=-1)addedge(id,llt,min(down[id],down[llt])-max(up[id],up[llt]));
					}
					addedge((*it).id,llt,inf);
					del.insert((*it));
				}
				for(auto to:del)s[x].erase(to);
			}
			s[x].insert(node(up[llt],down[llt],llt));
		}
		else{
//			for(int i=1;i<=tot;i++){
//				if(!o[i])
//				{
//					cout<<X[i]<<" "<<up[i]<<" "<<down[i]<<" "<<i<<endl;
//				}
//			}
//			cout<<endl;
//			for(int i=1;i<=n;i++){
//				for(auto to:s[i])cout<<i<<" "<<to.l<<" "<<to.r<<" "<<to.id<<endl;
//			}
			int x1,y1,x2,y2;
			scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
			int p1=bel(x1,y1),p2=bel(x2,y2);
			if(p1==-1||p2==-1){
				puts("-1");
				continue;
			}
			if(t.findroot(p1)!=t.findroot(p2)){
				puts("-1");
				continue;
			}
			int mn1=down[p1]-y1,mn2=down[p2]-y2;
			int ans=t.Getmn(p1,p2);
//			cout<<mn1<<" "<<mn2<<" "<<ans<<endl;
			printf("%d\n",min(min(mn1,mn2),ans));
//			return 0;
		}
	}
	return 0;
}
posted @ 2025-02-10 18:48  QZJ123456  阅读(51)  评论(0)    收藏  举报