传送门:AtCoder Regular Contest 164 - AtCoder
A.签到题,在此不做赘述
B - Switching Travel
这题本来该是秒的,但是因为没有考虑清楚环的问题而被卡半天,其实我们不难发现,要想使题目存在节点,就得让该节点出现一条环同时,而且环最后的头和尾颜色还必须得相等。直接dfs跑环加暴力枚举即可。
// #pragma GCC optimize(3) //O2优化开启
#include<bits/stdc++.h>
using namespace std;
#define int long long
typedef long long ll;
typedef pair<int,int> PII;
const int N=998244353;
const int MX=0x3f3f3f3f3f3f3f3f;
int n,m;
int id;
int ue[1000005];
void icealsoheat(){cin>>n>>m;vector<vector<int>>ve(n+5);for(int i=1;i<=m;i++){int l,r;cin>>l>>r;ve[l].push_back(r);ve[r].push_back(l);}vector<int>c(n+5,0);for(int i=1;i<=n;i++)cin>>ue[i];bool f=0;id=0;auto dfs=[&](auto self,int x,int fa)->void{for(auto i:ve[x]){if(c[i]||ue[i]==ue[x])continue;c[i]=id;self(self,i,x);}};for(int i=1;i<=n;i++){if(c[i]==0){id++;c[i]=id;dfs(dfs,i,-1);}for(auto j:ve[i]){if(ue[i]==ue[j]&&c[i]==c[j])f=1;} if(f)break;}// for(int i=1;i<=n;i++)cout<<c[i]<<"+++\n";// cout<<c[4]<<"----\n";if(f)puts("Yes");else puts("No");}
signed main(){ios::sync_with_stdio(false);cin.tie();cout.tie();int _;_=1;// cin>>_;while(_--){icealsoheat();}
}
C - Reversible Card Game
通过贪心的思想,双方若想都取最优,爱丽丝尽可能把差值大的值的从大的翻到小的,而鲍勃尽可能的在爱丽丝得手之前把没翻的牌(差值尽可能大的)拿走。然后,当正面大的牌都拿完的时候,鲍勃只需跟着爱丽丝拿,爱丽丝翻一张(把大的值翻上来),鲍勃就拿一张。
// #pragma GCC optimize(3) //O2优化开启
#include<bits/stdc++.h>
using namespace std;
#define int long long
typedef long long ll;
typedef pair<int,int> PII;
const int N=998244353;
const int MX=0x3f3f3f3f3f3f3f3f;
int n,m;
int a[1000005];
int b[1000005];
bool c[1000005];
struct we{int x;int cha;bool operator <(const we &k)const{return k.cha>cha;}
};
bool cmp(we ae,we be){return ae.cha<be.cha;
}
void icealsoheat(){cin>>n;priority_queue<we>q;vector<we>ve;priority_queue<we>qq;int ans=0;for(int i=1;i<=n;i++){cin>>a[i]>>b[i];ans+=min(a[i],b[i]);if(a[i]>b[i]){q.push({i,abs(a[i]-b[i])});}else{ve.push_back({i,abs(a[i]-b[i])});}}int op=0;while(q.size()){we now=q.top();q.pop();if(op==0){op^=1;ve.push_back({now});}if(!q.size())break;now=q.top();q.pop();if(op==1){op^=1;ans+=now.cha;}}// cout<<ans<<"+++\n";sort(ve.begin(),ve.end(),cmp);for(auto [i,j]:ve){if(op==0){ans+=j;}else op^=1;}cout<<ans;
}
signed main(){ios::sync_with_stdio(false);cin.tie();cout.tie();int _;_=1;// cin>>_;while(_--){icealsoheat();}
}
D - 1D Coulomb
一道很经典很妙的dp。
我们需要用dp迭代一下类似括号匹配的一样的结构。让+与-相互抵消。
dp[i][j]为值的和,i代表了前i个字母,j代表着+与-的差值状态。(n为+与-相等,0到n-1是-的较多,n+1到2*n是+较多)。hh[i][j]为当前方案的次数。
代码如下:
//#pragma GCC optimize(3)
#include<bits/stdc++.h>
using namespace std;
#define int long long
typedef long long ll;
typedef pair<int,int> PII;
const int N=998244353;
int n,m,k;
void icealsoheat(){cin>>n;string s;cin>>s;s=' '+s;vector<vector<int>>dp(2*n+5,vector<int>(2*n+5,0));vector<vector<int>>hh(2*n+5,vector<int>(2*n+5,0));hh[0][n]=1;for(int i=1;i<=2*n;i++){for(int j=0;j<=2*n;j++){if(s[i]=='+'||s[i]=='?'){if(j>0){dp[i][j]=(dp[i][j]+dp[i-1][j-1])%N;hh[i][j]=(hh[i][j]+hh[i-1][j-1])%N;}if(j<=n&&j>0){int v=n-j;v=v*2+1;dp[i][j]=(dp[i][j]+hh[i-1][j-1]*v%N)%N;}}if(s[i]=='-'||s[i]=='?'){if(j<2*n){dp[i][j]=(dp[i][j]+dp[i-1][j+1])%N;hh[i][j]=(hh[i][j]+hh[i-1][j+1])%N;}if(j>=n&&j<2*n){int v=j-n;v=v*2+1;dp[i][j]=(dp[i][j]+hh[i-1][j+1]*v%N)%N; }}}}cout<<dp[2*n][n];}
signed main(){ios::sync_with_stdio(false);cin.tie();cout.tie();int _;_=1;// cin>>_;while(_--){icealsoheat();}
}