終于開始補提了 重點 : C, E的倒著算, F的染色,G的相鄰的轉換; B - Hard Calculation
#include<iostream>#include<algorithm>#include<cstring>#include<vector>#include<cmath>#include<stack>#include<map>#definemid(l+r>>1)#definelowbit(x)(x&-x)usingnamespace std;typedeflonglong LL;typedef pair<int,int> PII;constint N =4e5+10, mod =1e9+7;voidmull(int&a, LL b){a = a*b%mod;return;}voidadd(int&a, LL b){a =(a+b)%mod;return;}intmain(){LL a, b;scanf("%lld%lld",&a,&b);while(a||b){if(a%10+ b%10>=10)returnputs("Hard"),0;a /=10; b /=10;}puts("Easy");return0;}
C - Cheese 思路 : 倒著算,直接減,和上海熱身賽B都好神奇。
#include<iostream>#include<algorithm>#include<cstring>#include<vector>#include<cmath>#include<stack>#include<map>#definemid(l+r>>1)#definelowbit(x)(x&-x)usingnamespace std;typedeflonglong LL;typedef pair<int,int> PII;constint N =3e5+10, mod =998244353;voidmull(int&a, LL b){a = a*b%mod;return;}voidadd(int&a, LL b){a =(a+b)%mod;return;}int n, w;
PII a[N];intmain(){scanf("%d%d",&n,&w);for(int i =1;i <= n;i ++){int x, y;scanf("%d%d",&x,&y);a[i]={-x, y};}sort(a+1, a+n+1);LL ans =0;for(int i =1;i <= n;i ++){int mi =min(a[i].second, w);ans +=(LL)mi*a[i].first;w -= mi;}cout<<-ans<<endl;return0;}
D - Longest X 思路 : 雙指針或二分,練一下雙指針,哎。
#include<iostream>#include<algorithm>#include<cstring>#include<vector>#include<cmath>#include<stack>#include<map>#definemid(l+r>>1)#definelowbit(x)(x&-x)usingnamespace std;typedeflonglong LL;typedef pair<int,int> PII;constint N =2e5+10, mod =1e9+7;voidmull(int&a, LL b){a = a*b%mod;return;}voidadd(int&a, LL b){a =(a+b)%mod;return;}char c[N];intmain(){int k;scanf("%s%d", c,&k);int num =0, l =0, r =0, ans =0;while(c[r]){if(c[r]=='X') r++;elseif(num == k) num -= c[l++]=='.';elseif(num < k) num ++, r++;ans =max(ans, r-l);}cout<<ans<<endl;return0;}
E - Graph Destruction 思路 :從后往前算,倒著并查集合并。
#include<iostream>#include<algorithm>#include<cstring>#include<vector>#include<cmath>#include<stack>#include<queue>#definemid(l+r>>1)#definelowbit(x)(x&-x)usingnamespace std;typedeflonglong LL;typedef pair<int,int> PII;constint N =2e5+10, mod =1e9+7;vector<int>G[N];int fa[N], num =0;intfind(int u){return fa[u]== u ? fa[u]:fa[u]=find(fa[u]);}voiddfs(int u){if(!u)return;int t = num;num++;int y =find(u);for(auto x : G[u]){int a =find(x);if(a != y) num--, fa[a]= y;}dfs(u-1);cout<<t<<endl;return;}intmain(){int n, m;scanf("%d%d",&n,&m);for(int i =1;i <= n;i ++) fa[i]= i;while(m --){int a, b;scanf("%d%d",&a,&b);if(a > b)swap(a, b);G[a].push_back(b);}dfs(n);return0;}
F - Make Bipartite 思路 : dp,給每個點染色之后就可以清晰的得到要刪哪條邊了,但是這是個封閉圖形,題解就確定了起點的顏色,然后算到第n個點,這時候先不考慮n到1的邊 。 然后再枚舉n和1的四種顏色組合,枚舉的時候要注意n到0的邊已經刪過了,因為這個wa了兩次。
#include<iostream>#include<algorithm>#include<cstring>#include<vector>#include<cmath>#include<stack>#include<map>#definemid(l+r>>1)#definelowbit(x)(x&-x)usingnamespace std;typedeflonglong LL;typedef pair<int,int> PII;constint N =3e5+10, mod =998244353;voidmull(int&a, LL b){a = a*b%mod;return;}voidadd(int&a, LL b){a =(a+b)%mod;return;}LL dp[N][2][2];int a[N], b[N];intmain(){int n;scanf("%d",&n);for(int i =1;i <= n;i ++)scanf("%d", a+i);for(int i =1;i <= n;i ++)scanf("%d", b+i);memset(dp,0x7f,sizeof dp);dp[1][0][0]= a[1];dp[1][1][1]=0;for(int i =2;i <= n;i ++){dp[i][1][0]=min(dp[i-1][1][0]+b[i-1], dp[i-1][0][0]);dp[i][1][1]=min(dp[i-1][1][1]+b[i-1], dp[i-1][0][1]);dp[i][0][0]=min(dp[i-1][1][0], dp[i-1][0][0]+b[i-1])+a[i];dp[i][0][1]=min(dp[i-1][1][1], dp[i-1][0][1]+b[i-1])+a[i];}cout<<min(min(dp[n][0][0], dp[n][1][1])+ b[n],min(dp[n][1][0], dp[n][0][1]));return0;}
G - Longest Y
#include<iostream>#include<algorithm>#include<cstring>#include<vector>#include<cmath>#include<stack>#include<map>#definemid(l+r>>1)#definelowbit(x)(x&-x)usingnamespace std;typedeflonglong LL;typedef pair<int,int> PII;constint N =3e5+10, mod =998244353;voidmull(int&a, LL b){a = a*b%mod;return;}voidadd(int&a, LL b){a =(a+b)%mod;return;}int b[N], idx;// 看哪個題解的,放到一起連續就是坐標減去指數相等。
string c;
LL k, a[N];// a數組是前綴和,方便計算一段區間放到的最小步數; boolch(int len){for(int r = len;r <= idx;r ++){int l = r-len+1, lle = mid-l+1;LL sum =(LL)b[mid]*lle -(a[mid]-a[l-1])+ a[r]-a[mid]-(LL)b[mid]*(len-lle);if(sum<=k)return1;}return0;}intmain(){cin>>c>>k;for(int i =0;i < c.size();i ++)if(c[i]=='Y')b[++idx]= i-idx;sort(b+1, b+idx+1);for(int i =1;i <= idx;i ++)a[i]= a[i-1]+b[i];int l =0, r = idx+1;while(l < r)// 二分都是找到連續區間的右邊的左端點; {if(ch(mid))l = mid+1;else r = mid;}cout<<--l<<endl;return0;}