细微颗粒布满了整个房间 点燃通向毁灭实验的导线 所有成果于今天引爆炸裂 这不可逆爱恋从此灰飞烟灭

test49

可能是这辈子最后一场模拟赛了(?


文件改名

先删掉自环,连成图,发现是基环树森林可能扣掉一些边,不管怎么说就是要额外做环次操作了,那并查集看一下边数点数一不一样就好了。

#include<bits/stdc++.h>
#define int long long
#define up(i,l,r) for(int i=l; i<=r; ++i)
#define dn(i,r,l) for(int i=r; i>=l; --i)
#define pb push_back 

using namespace std;

const int N=200005;

int n, m, dsu[N], siz[N], val[N], ans;
map<string,int> id;

int get(int x) { return x==dsu[x]?x:dsu[x]=get(dsu[x]); }

void merge(int x,int y) {
	if((x=get(x))==(y=get(y))) return;
	val[y]+=val[x], siz[y]+=siz[x], dsu[x]=y;
}

signed main() {
	freopen("files.in","r",stdin);
	freopen("files.out","w",stdout);
	ios::sync_with_stdio(0);
	cin.tie(0);
	cin >> n;
	up(i,1,n) {
		string l, r;
		cin >> l >> r;
		if(l==r) { --ans; continue; }
		if(!id[l]) id[l]=++m, dsu[m]=m, siz[m]=1;
		if(!id[r]) id[r]=++m, dsu[m]=m, siz[m]=1;
		merge(id[l],id[r]), ++val[get(id[r])];
	}
	up(i,1,m) if(dsu[i]==i&&val[i]==siz[i]) ++ans;
	cout << n+ans << '\n'; 
	return 0;
}

怪物猎人

贡献只有在 \(k+1\) 轮杀怪物减少 \((a+kd)(b+kd)=ab+(kd)^2+kd(a+b)\),那肯定按照 \(a+b\downarrow\) 来加,排序之后做背包即可。

#include<bits/stdc++.h>
#define int long long
#define up(i,l,r) for(int i=l; i<=r; ++i)
#define dn(i,r,l) for(int i=r; i>=l; --i)
#define pii pair<int,int>
#define mp make_pair
#define fir first
#define sec second 

using namespace std;

const int N=3005;

int n, m, d, f[N][N];
pii a[N];

int calc(int i,int j) { return (a[i].fir+(j-1)*d)*(a[i].sec+(j-1)*d); }

signed main() {
	freopen("hunter.in","r",stdin);
	freopen("hunter.out","w",stdout);
	ios::sync_with_stdio(0);
	cin.tie(0);
	cin >> n >> m >> d;
	up(i,1,n) cin >> a[i].fir;
	up(i,1,n) cin >> a[i].sec;
	sort(a+1,a+1+n,[](pii i,pii j){return i.fir+i.sec>j.fir+j.sec;});
	up(i,1,n) {
		up(j,1,i-1) f[i][j]=min(f[i-1][j],f[i-1][j-1]+calc(i,j));
		f[i][i]=f[i-1][i-1]+calc(i,i);
	}
	while(m--) {
		int h, ans;
		cin >> h;
		ans=lower_bound(f[n]+1,f[n]+1+n,h)-f[n]-1;
		cout << ans << ' ';
	}
	return 0;
}

魔术帽游戏

操作先拆成两个平行的操作,对于依次有操作 \((a,b),(b,c)\) 连接对应的操作编号。查询就是找到第一个 \((x,)\) 然后一直跳直到 \(>r\),快速查找可以 vector,快速跳可以倍增。

#include<bits/stdc++.h>
#define int long long
#define up(i,l,r) for(int i=l; i<=r; ++i)
#define dn(i,r,l) for(int i=r; i>=l; --i)
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
#define fir first
#define sec second 

using namespace std;

const int N=500005, M=__lg(N)+1; 

int n, m, q, T, tot, a[N], b[N], id[N][2], fa[N][M], lst[N];
vector<int> to[N];

signed main() {
	freopen("magic.in","r",stdin);
	freopen("magic.out","w",stdout);
	ios::sync_with_stdio(0);
	cin.tie(0);
	cin >> n >> m >> q, T=__lg(m);
	up(i,1,m) cin >> a[i] >> b[i];
	up(i,1,m) {
		id[i][0]=++tot, id[i][1]=++tot;
		to[a[i]].pb(id[i][0]), to[b[i]].pb(id[i][1]);
	}
	dn(i,m,1) {
		fa[id[i][0]][0]=lst[b[i]];
		fa[id[i][1]][0]=lst[a[i]];
		lst[a[i]]=id[i][0], lst[b[i]]=id[i][1];
		up(j,1,T) {
			fa[id[i][0]][j]=fa[fa[id[i][0]][j-1]][j-1];
			fa[id[i][1]][j]=fa[fa[id[i][1]][j-1]][j-1];
		}
	}
	while(q--) {
		int x, l, r;
		cin >> x >> l >> r;
		int p=lower_bound(to[x].begin(),to[x].end(),id[l][0])-to[x].begin();
		if(p>=(int)to[x].size()||to[x][p]>id[r][1]) { cout << x << '\n'; continue; }
		p=to[x][p];
		dn(i,T,0) if(fa[p][i]&&fa[p][i]<=id[r][1]) p=fa[p][i];
		if(p%2==1) cout << b[(p+1)/2] << '\n';
		if(p%2==0) cout << a[p/2] << '\n';
	}
	return 0;
}

计算树

直接倍增就好了。

#include<bits/stdc++.h>
#define int long long
#define up(i,l,r) for(int i=l; i<=r; ++i)
#define dn(i,r,l) for(int i=r; i>=l; --i)
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
#define fir first
#define sec second 

using namespace std;

const int N=100005, M=__lg(N)+1, P=19491001;

int n, m, T, val[N], dep[N], fa[N][M];
pii f[N][M], g[N][M];
vector<pii> to[N];

pii operator+(const pii i,const pii j) {
	return mp(i.fir*j.fir%P,(i.sec*j.fir%P+j.sec)%P);
}

void dfs(int x,int fad) {
	dep[x]=dep[fad]+1, fa[x][0]=fad;
	up(i,1,T) {
		fa[x][i]=fa[fa[x][i-1]][i-1];
		f[x][i]=f[x][i-1]+f[fa[x][i-1]][i-1];
		g[x][i]=g[fa[x][i-1]][i-1]+g[x][i-1];
	}
	for(pii u:to[x]) {
		int y=u.fir, opt=u.sec;
		if(y==fad) continue;
		if(opt==1) f[y][0]=mp(1,+val[x]), g[y][0]=mp(1,+val[y]);
		if(opt==2) f[y][0]=mp(1,-val[x]), g[y][0]=mp(1,-val[y]);
		if(opt==3) f[y][0]=mp(val[x],0), g[y][0]=mp(val[y],0);
		dfs(y,x);
	}
}

int lca(int x,int y) {
	if(dep[x]<dep[y]) swap(x,y);
	dn(i,T,0) if(dep[fa[x][i]]>=dep[y]) x=fa[x][i];
	if(x==y) return x;
	dn(i,T,0) if(fa[x][i]!=fa[y][i]) x=fa[x][i], y=fa[y][i];
	return fa[x][0];
}

signed main() {
	freopen("tree.in","r",stdin);
	freopen("tree.out","w",stdout);
	ios::sync_with_stdio(0);
	cin.tie(0);
	cin >> n >> m, T=__lg(n);
	up(i,1,n) cin >> val[i], val[i]%=P;
	up(i,2,n) {
		int x, y, z;
		cin >> x >> y >> z;
		to[x].pb(mp(y,z));
		to[y].pb(mp(x,z));
	}
	dfs(1,0);
	while(m--) {
		int x, y, p, sav;
		pii ans, l(1,0), r(1,0);
		cin >> x >> y;
		sav=val[x], p=lca(x,y);
		dn(i,T,0) if(dep[fa[x][i]]>=dep[p]) l=l+f[x][i], x=fa[x][i];
		dn(i,T,0) if(dep[fa[y][i]]>=dep[p]) r=g[y][i]+r, y=fa[y][i];
		ans=l+r;
		cout << ((ans.fir*sav%P+ans.sec)%P+P)%P << '\n';
	}
	return 0;
}
posted @ 2025-11-27 11:12  Hypoxia571  阅读(11)  评论(0)    收藏  举报