想要寻找催化剂破坏牢固的键 想用相同热量找回最初感觉 麻木重复的过程逐渐取代新鲜 心腐蚀了一遍一遍

test41


输出字符串

按照题意模拟即可。

#pragma GCC optimize(1,2,3,"Ofast","inline")
#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=100005, M=26;

int n, T, cnt[N];
string s[N];
vector<int> str[M];

bool operator<(const string i,const string j) {
	int l=min(i.size(),j.size());
	up(u,0,l-1) if(i[u]!=j[u]) return i[u]<j[u];
	return i.size()<j.size();
}

signed main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cin >> n >> T;
	up(i,1,n) {
		cin >> s[i];
		str[s[i][0]-'a'].pb(i);
	}
	up(i,0,25) sort(str[i].begin(),str[i].end(),[](int i,int j){return s[i]<s[j];});
	while(T--) {
		char u;
		cin >> u;
		int v=u-'a';
		if(!str[v].size()) cout << '\n';
		else {
			cout << s[str[v][cnt[v]]] << '\n';
			cnt[v]=(cnt[v]+1)%(int)str[v].size();
		}
	}
	return 0;
}

最优排列翻转

考虑一个 \(p_i\) 只有在 \(\frac{i+p_i}{2}\) 为中点(或者中缝)时操作才会有正贡献,被操作区间包含且不为中点且原先贡献的操作才会有负贡献。后者是简单关系,不妨把前者挂在中点上,然后枚举中间考虑怎么做,发现可以只取挂上去的长度,那排序之后枚举就好了。

#pragma GCC optimize(1,2,3,"Ofast","inline")
#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=500005;

int n, p[N], sum[N], cnt, ans;
vector<int> L[N], R[N];

signed main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cin >> n;
	up(i,1,n) cin >> p[i];
	up(i,1,n) {
		sum[i]=sum[i-1]+(p[i]==i);
		if(p[i]!=i) {
			int l=(i+p[i])/2, r=(abs(i-p[i])+1)/2;
			if((i+p[i])%2==0) L[l].pb(r); else R[l].pb(r); 
		}
	}
	up(i,1,n) {
		cnt=0, sort(L[i].begin(),L[i].end());
		for(int u:L[i]) ans=max(ans,(++cnt)-(sum[i+u-1]-sum[i-u])+(p[i]==i));
		cnt=0, sort(R[i].begin(),R[i].end());
		for(int u:R[i]) ans=max(ans,(++cnt)-(sum[i+u]-sum[i-u]));
	}
	cout << ans << '\n';
	return 0;
}

比赛

不会做了半天发现自己不知道花果山为 \(1\) /fad

考虑把 \(1\) 提成根,设 \(f_i\) 为从 \(i\) 开始走的答案,转移就往 \(k\) 内的祖先转移,这个可以 dfs 的时候取栈的后缀,线段树优化 dp 即可。

#pragma GCC optimize(1,2,3,"Ofast","inline")
#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 ls(p) (p<<1)
#define rs(p) (p<<1|1)

using namespace std;

const int N=200005;

int n, m, T, dep[N], f[N], tr[N<<2];
vector<int> to[N];
vector<pii> lap[N]; 

void modify(int x,int v,int p=1,int s=1,int e=n) {
	if(s==e) return tr[p]=v, void();
	int mid=(s+e)>>1;
	if(x<=mid) modify(x,v,ls(p),s,mid);
	if(x>mid) modify(x,v,rs(p),mid+1,e);
	tr[p]=min(tr[ls(p)],tr[rs(p)]);
}

int query(int l,int r,int p=1,int s=1,int e=n) {
	if(l<=s&&e<=r) return tr[p];
	int mid=(s+e)>>1, res=1e18;
	if(l<=mid) res=query(l,r,ls(p),s,mid);
	if(r>mid) res=min(res,query(l,r,rs(p),mid+1,e));
	return res;
}

void dfs(int x,int fad) {
	dep[x]=dep[fad]+1;
	if(dep[x]>1) for(pii u:lap[x]) f[x]=min(f[x],query(dep[x]-u.first,dep[x]-1)+u.second);
	modify(dep[x],f[x]);
	for(int y:to[x]) if(y!=fad) dfs(y,x);
}

signed main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cin >> n >> m >> T;
	up(i,2,n) {
		int u, v;
		cin >> u >> v;
		to[u].pb(v);
		to[v].pb(u); 
	}
	while(m--) {
		int x, k, v;
		cin >> x >> k >> v;
		lap[x].pb(mp(k,v));
	}
	memset(f,0x3f,sizeof(f));
	memset(tr,0x3f,sizeof(tr));
	f[1]=0, dfs(1,0);
	while(T--) {
		int x;
		cin >> x;
		cout << f[x] << '\n';
	}
	return 0;
}

圣杯战争

首先肯定是一条边来贡献,假设不要某条边而要起点终点相同的另一条链,那么不如要链上肯定存在的连接不同颜色的边,所以题目变成了动态修改颜色+查询两端颜色不同的边的最小权。

发现可以取 mst 出来,然后瓶颈在于暴力复杂度是 \(O(\sum in_u)\) 的,然后这个时候没睡好被根号分治占领大脑了,所以感觉 mst 带不来对根号分治的优化扔掉了。然后你可以直接上一个根号分治,大对大、小对小的贡献是容易的,然后考虑怎么处理小对大的贡献,可以在大点上维护某种颜色的答案是多少,然后再快速查找最大答案、这个排序之后只用遍历俩颜色。具体而言,维护两个 multiset,一个储存所有儿子的信息,快速查询某种颜色的最小权,一个储存所有颜色的信息,对每种颜色的权值排序,都要支持动态加删。

然后稍微有一点点被卡常,本地 o3 <2s 但是 lgj 机子稍微慢一点,捡回来扔掉的 mst,可以给边的规模 \(\times \frac{1}{2}\) 然后就可以过惹。所以话又说回来了,你把 mst 提出来,上面的做法从小对大改成儿子对父亲,就是单 \(\log\) 做法了,感觉写起来估计差不多吧(

#pragma GCC optimize(1,2,3,"Ofast","inline")
#include<bits/stdc++.h>
#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=200005;

int n, m, K, T, B, gp[N], in[N], dsu[N];
vector<int> diff;
vector<pii> to[N];
multiset<int> com;
multiset<pii> L[N], R[N];
map<pii,int> dis;
struct node { int x, y, w; } p[N<<1];

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

signed main() {
   ios::sync_with_stdio(0);
   cin.tie(0);
   cin >> n >> m >> K >> T, B=sqrt(2*m);
   up(i,1,m) cin >> p[i].x >> p[i].y >> p[i].w; 
   sort(p+1,p+1+m,[](node i,node j){return i.w<j.w;});
   up(i,1,n) dsu[i]=i;
   up(i,1,m) {
   	int u=p[i].x, v=p[i].y, w=p[i].w;
   	int x=get(u), y=get(v);
   	if(x==y) continue;
   	++in[u], ++in[v], dsu[x]=y;
   	dis[mp(u,v)]=dis[mp(v,u)]=w;
   	to[u].pb(mp(v,w));
   	to[v].pb(mp(u,w));
   }
   up(i,1,n) cin >> gp[i];
   up(i,1,n) in[i]=(in[i]>B);
   up(i,1,n) {
   	for(pii u:to[i]) {
   		int j=u.fir, w=u.sec;
   		if(i<j&&in[i]==in[j]&&gp[i]!=gp[j]) com.insert(w);
   	}
   	if(in[i]) {
   		diff.pb(i);
   		for(pii u:to[i]) {
   			int j=u.fir, w=u.sec;
   			if(in[j]) continue;
   			auto it=L[i].lower_bound(mp(gp[j],0));
   			if(it==L[i].end()||it->fir!=gp[j]) R[i].insert(mp(w,gp[j]));
   			else if(w<it->sec) R[i].erase(R[i].find(mp(it->sec,it->fir))), R[i].insert(mp(w,gp[j]));
   			L[i].insert(mp(gp[j],w));
   		}
   		for(pii u:R[i]) if(u.sec!=gp[i]) { com.insert(u.fir); break; }
   	}
   }
   while(T--) {
   	int i, pre, suf;
   	cin >> i >> suf;
   	pre=gp[i], gp[i]=suf;
   	if(in[i]) {
   		for(int j:diff) {
   			if(dis.find(mp(i,j))==dis.end()) continue;
   			int w=dis[mp(i,j)];
   			gp[i]=pre;
   			if(gp[i]==gp[j]) com.erase(com.find(w));
   			gp[i]=suf;
   			if(gp[i]==gp[j]) com.insert(w);
   		}
   		gp[i]=pre;
   		for(pii u:R[i]) if(u.sec!=gp[i]) { com.erase(com.find(u.fir)); break; }
   		gp[i]=suf;
   		for(pii u:R[i]) if(u.sec!=gp[i]) { com.insert(u.fir); break; }
   	}
   	else {
   		for(pii u:to[i]) {
   			int j=u.fir, w=u.sec;
   			if(in[j]) {
   				gp[i]=pre;
   				for(pii u:R[j]) if(u.sec!=gp[j]) { com.erase(com.find(u.fir)); break; }
   				L[j].erase(L[j].find(mp(gp[i],w)));
   				if(R[j].find(mp(w,gp[i]))!=R[j].end()) {
   					R[j].erase(R[j].find(mp(w,gp[i])));
   					auto it=L[j].lower_bound(mp(gp[i],0));
   					if(it!=L[j].end()&&it->fir==gp[i]) R[j].insert(mp(it->sec,it->fir));
   				}
   				gp[i]=suf;
   				auto it=L[j].lower_bound(mp(gp[i],0));
   				if(it==L[j].end()||it->fir!=gp[i]) R[j].insert(mp(w,gp[i]));
   				else if(w<it->sec) R[j].erase(R[j].find(mp(it->sec,it->fir))), R[j].insert(mp(w,gp[i]));
   				L[j].insert(mp(gp[i],w));
   				for(pii u:R[j]) if(u.sec!=gp[j]) { com.insert(u.fir); break; }
   			}
   			else {
   				gp[i]=pre;
   				if(gp[i]!=gp[j]) com.erase(com.find(w));
   				gp[i]=suf;
   				if(gp[i]!=gp[j]) com.insert(w);
   			}
   		}
   	}
   	cout << *com.begin() << '\n';
   }
   return 0;
}
posted @ 2025-11-17 16:06  Hypoxia571  阅读(10)  评论(0)    收藏  举报