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

浙公网安备 33010602011771号