Educational Codeforces Round 168 (Rated for Div. 2) 补题记录(A~E)
A
直接暴力枚举字符添加在哪里,以及添加的字符是什么即可。
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=500100;
signed main(){
int T;
cin>>T;
while(T--){
string s;
cin>>s;
string ans;
int mi=-1e18;
for(int i=0;i<=s.size();++i){
for(char ch='a';ch<='z';++ch){
string aa;
for(int j=0;j<i;++j)aa+=s[j];
aa+=ch;
for(int j=i;j<s.size();++j)aa+=s[j];
int cost=2;
for(int i=1;i<aa.size();++i)
if(aa[i]==aa[i-1])++cost;
else ++cost,++cost;
if(mi<cost)
mi=cost,ans=aa;
}
}
cout<<ans<<'\n';
}
}
B
枚举每一个格子,现在需要计算当前的连通块数目:考虑使用动态维护图连通性的科技 考虑判断一个字符被染色之后对答案造成的贡献:如果这个格子位于角落那么显然不可以,否则这个格子和
问题在于判定格子是否会产生贡献:若其周围三个格子都为空,且其左上(下)角和右上(下)角的格子都不空,那么让这个格子不空之后可以恰好产生三个连通块。因此直接判断即可。时间复杂度为
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=500100;
char a[2][N];
signed main(){
int T;
cin>>T;
while(T--){
int n;cin>>n;
for(int i=0;i<2;++i)scanf("%s",a[i]);
int xx=0;for(int i=0;i<2;++i)for(int j=0;j<n;++j)
if(a[i][j]=='.')++xx;if(xx==0)cout<<"0\n";
else{
int cnt=0;
for(int i=0;i<2;++i)for(int j=0;j<n;++j)
if(a[i][j]=='.'){
if(i==0){
if((j!=0&&a[1][j-1]=='x'&&a[0][j-1]!='x')&&(j!=n-1&&a[1][j+1]=='x'&&a[0][j+1]!='x')&&a[1][j]!='x')++cnt;
}else{
if((j!=0&&a[0][j-1]=='x'&&a[1][j-1]!='x')&&(j!=n-1&&a[0][j+1]=='x'&&a[1][j+1]!='x')&&a[0][j]!='x')++cnt;
}
}
cout<<cnt<<'\n';
}
}
}
C
反悔贪心板子题。考虑尽量的让当前字符为右括号。如果到某一个前缀的时候右括号数量大于左括号数量,那么就贪心的让当前最后一个被变为右括号的括号变为左括号。这个变为右括号的括号集合用一个栈维护即可。时间复杂度为
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=500100;
char s[N];
signed main(){
int T;
cin>>T;
while(T--){
int n;cin>>n;
scanf("%s",s+1);
int cnt=0;
int c1=n/2,c2=n/2;
for(int i=1;i<=n;++i)
if(s[i]=='(')--c1;
else if(s[i]==')')--c2;
int pre=0;
stack<int>laright;
for(int i=1;i<=n;++i){
if(s[i]=='_'){
if(!pre)pre=1,s[i]='(',--c1;
else if(!c2)++pre,s[i]='(',--c1;
else --pre,--c2,s[i]=')',laright.emplace(i);
}else if(s[i]=='(')++pre;
else{
--pre;
if(pre<0){
pre+=2;
int t=laright.top();laright.pop();
s[t]='(';--c1,++c2;
}
}
}
stack<int>stk;
for(int i=1;i<=n;++i)
if(s[i]=='(')stk.push(i);
else{
cnt+=i-stk.top();
stk.pop();
}
cout<<cnt<<'\n';
}
}
D
不是,这题怎么才 (注:差点没切,wa 逆天点 #19)
看到最大值考虑二分然后将问题转化为判定问题。设现在判定答案
此时根节点值必须至少为
现在强制令根节点的值不小于
然后就是计算是否有一组方案满足其他结点的值全部大于等于
把树从上往下遍历一遍。对于每一个非叶子结点
然后这个题难点是溢出问题,建议使用 Python。
#pragma GCC optimize(3)
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=500100;
int a[N],n,jia[N];
vector<int>z[N];
__int128 b[N];
void dfs(int u,int fa,__int128 qian){
b[u]-=qian;
if(qian>1e12&&b[u]<0){
b[u]=-233;
return;
}
if(b[u]>=0){
for(auto&v:z[u])
if(v!=fa)dfs(v,u,qian);
}else{
int ok=1;
for(auto&v:z[u])
if(v!=fa)dfs(v,u,qian-b[u]),ok=0;
if(!ok)
b[u]=0;
}
}
//判定根节点的值最后是否可以为p
bool check(int p){
for(int i=1;i<=n;++i)b[i]=a[i],jia[i]=0;
int jiax=max((__int128)(0),p-b[1]);
b[1]+=jiax;
for(int i=2;i<=n;++i)b[i]-=jiax;
dfs(1,0,0);
int ok=1;
for(int i=1;i<=n;++i)if(b[i]<0){ok=0;break;}
if(b[1]<p)ok=0;
return ok;
}
signed main(){
ios_base::sync_with_stdio(0);
cin.tie(0);
int T;
cin>>T;
while(T--){
cin>>n;
for(int i=1;i<=n;++i)cin>>a[i],z[i].clear();
for(int i=2;i<=n;++i){
int u=i,v;cin>>v;
z[u].emplace_back(v),z[v].emplace_back(u);
}
int l=1,r=(int)(2e18)+2333,best=0;
while(l<=r){
int mid=l+r>>1;
if(check(mid))best=mid,l=mid+1;
else r=mid-1;
}
cout<<best<<'\n';
}
}
E
Upd:FST 了,还需要继续卡常,很懒所以不卡了
使用伟大的数据结构。考虑对于每一个不同的
更具体的说,二分一段区间
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
using namespace std;
const int N=200100;
vector<pair<int,int>>scc[N];
struct qwq{
int l,r,sum;
}z[N<<5];
int idx,a[N],rt[N],res[N];
int modify(int l,int r,int &rt,int p,int v){
int pp=++idx;z[pp]=z[rt];
if(l==r){
z[pp].sum+=v;
return pp;
}
int mid=l+r>>1;
if(p<=mid)
z[pp].l=modify(l,mid,z[rt].l,p,v);
else
z[pp].r=modify(mid+1,r,z[rt].r,p,v);
z[pp].sum=z[z[pp].l].sum+z[z[pp].r].sum;
return pp;
}
int query(int p,int l,int r,int k){
if(l>=k)
return z[p].sum;
int mid=l+r>>1;
if(k>mid)
return query(z[p].r,mid+1,r,k);
return query(z[p].l,l,mid,k)+z[z[p].r].sum;
}
signed main(){
ios_base::sync_with_stdio(0);
cin.tie(0);
int n,q;cin>>n>>q;
for(int i=1;i<=n;++i)cin>>a[i];
for(int i=1;i<=q;++i){
int v,x;cin>>v>>x;
scc[x].emplace_back(v,i);
}
for(int i=1;i<=n;++i)
rt[i]=modify(1,200001,rt[i-1],a[i],1);
for(int i=1;i<=n;++i)
sort(scc[i].begin(),scc[i].end());
for(int i=1;i<=n;++i)
if(scc[i].size()){
int p=1,nowlevel=1;
while(p<=scc[i].back().first){
int l=p,r=scc[i].back().first,best=-1;
//计算区间[l,r]中有多少个数>=now
int presolve=query(rt[p-1],1,200001,nowlevel);
while(l<=r){
int mid=l+r>>1;
if(query(rt[mid],1,200001,nowlevel)-presolve>=i)
best=mid,r=mid-1;
else
l=mid+1;
}
int lp;
if(best==-1)
lp=n;
else
lp=best;
l=0,r=scc[i].size()-1,best=-1;
while(l<=r){
int mid=l+r>>1;
if(scc[i][mid].first>=p)
best=mid,r=mid-1;
else
l=mid+1;
}
if(best!=-1){
for(int j=best;j<scc[i].size();++j)
if(scc[i][j].first>lp)break;
else if(a[scc[i][j].first]>=nowlevel)
res[scc[i][j].second]=1;
}
p=lp+1;
++nowlevel;
}
}
for(int i=1;i<=q;++i)
if(res[i])cout<<"YES\n";
else cout<<"NO\n";
}
本文来自博客园,作者:yhbqwq,转载请注明原文链接:https://www.cnblogs.com/yhbqwq/p/18334103,谢谢QwQ
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全网最简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程
· .NET 10 首个预览版发布,跨平台开发与性能全面提升
· 《HelloGitHub》第 107 期
· 全程使用 AI 从 0 到 1 写了个小工具
· 从文本到图像:SSE 如何助力 AI 内容实时呈现?(Typescript篇)