日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

牛客练习赛 57——manacher算法 树形dp?

發(fā)布時間:2023/12/3 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 牛客练习赛 57——manacher算法 树形dp? 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

A - Tic-Tac-Toe

直接考慮每個人8種贏的情況即可。

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0) #pragma GCC optimize(2) #include<iostream> #include<algorithm> using namespace std; const int N=5; char g[N][N]; int main() {//IO;int T=1;cin>>T;while(T--){for(int i=1;i<=3;i++) cin>>g[i]+1;bool ok1=0,ok2=0;if(g[1][1]=='A'&&g[1][2]=='A'&&g[1][3]=='A') ok1=1;if(g[2][1]=='A'&&g[2][2]=='A'&&g[2][3]=='A') ok1=1;if(g[3][1]=='A'&&g[3][2]=='A'&&g[3][3]=='A') ok1=1;if(g[1][1]=='A'&&g[2][1]=='A'&&g[3][1]=='A') ok1=1;if(g[1][2]=='A'&&g[2][2]=='A'&&g[3][2]=='A') ok1=1;if(g[1][3]=='A'&&g[2][3]=='A'&&g[3][3]=='A') ok1=1;if(g[1][1]=='A'&&g[2][2]=='A'&&g[3][3]=='A') ok1=1;if(g[1][3]=='A'&&g[2][2]=='A'&&g[3][1]=='A') ok1=1;if(g[1][1]=='B'&&g[1][2]=='B'&&g[1][3]=='B') ok2=1;if(g[2][1]=='B'&&g[2][2]=='B'&&g[2][3]=='B') ok2=1;if(g[3][1]=='B'&&g[3][2]=='B'&&g[3][3]=='B') ok2=1;if(g[1][1]=='B'&&g[2][1]=='B'&&g[3][1]=='B') ok2=1;if(g[1][2]=='B'&&g[2][2]=='B'&&g[3][2]=='B') ok2=1;if(g[1][3]=='B'&&g[2][3]=='B'&&g[3][3]=='B') ok2=1;if(g[1][1]=='B'&&g[2][2]=='B'&&g[3][3]=='B') ok2=1;if(g[1][3]=='B'&&g[2][2]=='B'&&g[3][1]=='B') ok2=1;if(ok1&&ok2) cout<<"invalid\n";else if(ok1) cout<<"Yes\n";else if(ok2) cout<<"No\n";else cout<<"draw\n";}return 0; }

B - 打 boss

如果第一次都能打死就不考慮回復(fù)血的情況
如果第一次打不死并且回血不少于掉血肯定永遠(yuǎn)打不死
人死之前最多能攻擊?h1a2?\lceil\frac{h_1}{a_2} \rceil?a2?h1???次,如果死之前打不死(需要干掉h2+m?h1a2?1?h2+m\lceil\frac{h_1}{a_2}-1 \rceilh2+m?a2?h1???1?血量)那么就打不死,否則能打死。

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0) #pragma GCC optimize(2) #include<set> #include<map> #include<cmath> #include<queue> #include<string> #include<vector> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<unordered_map> using namespace std; typedef long long ll; typedef pair<int,int> pii; int main() {IO;int T=1;cin>>T;while(T--){ll h1,h2;ll a1,a2;ll m;cin>>h1>>h2>>a1>>a2>>m;if(h2<=a1) cout<<"Yes\n";else if(m>=a1) cout<<"No\n";else if(((h1+a2-1)/a2)*a1<h2+m*((h1+a2-1)/a2-1)) cout<<"No\n";else cout<<"Yes\n";}return 0;}

C - 裝貨物

搜索渣渣。沒經(jīng)歷過偏分的oi沒能成為搜索king

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0) #pragma GCC optimize(2) #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int N=30; ll w[N]; int n,m,W; ll now[N]; bool ok; void dfs(int u,int cnt) {if(ok) return;//這個優(yōu)化直接讓我過了if(u>n){ok=1;return;}for(int i=1;i<=cnt;i++){if(now[i]+w[u]<=W){now[i]+=w[u];dfs(u+1,cnt);now[i]-=w[u];}}if(w[u]<=W&&cnt+1<=m){now[cnt+1]=w[u];dfs(u+1,cnt+1);now[cnt+1]-=w[u];} } int main() {IO;int T=1;cin>>T;while(T--){cin>>n>>m>>W;for(int i=1;i<=n;i++) cin>>w[i];sort(w+1,w+1+n);reverse(w+1,w+1+n);ok=0;memset(now,0,sizeof now);dfs(1,0);if(ok) cout<<"Yes\n";else cout<<"No\n";}return 0;}

D - 回文串

學(xué)了一下manacher算法,模板++
用manacher算法求后p[i]-1即表示原字符串回文序列長度,而且經(jīng)過對字符串進(jìn)行添加*操作后最終每個回文字符串的最左或右端一定是*。
對于本題需求不相交且長度和最大的非空回文子串,我們可以嘗試枚舉劃分點,左邊最長的回文子串+右邊最長的回文子串(預(yù)處理前綴后綴即可)即可求出。

注意:由于每個回文字符串的最左或右端一定是*,一定不會出現(xiàn)相交的情況。
非空想想不難知道只有在整個字符串都是回文串的情況下非空才會和不非空的結(jié)果不一樣(其他情況非空的結(jié)果一定更優(yōu))。我們需要特判整個字符串是回文串的情況。

#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int N=400010; int n; char s[N]; int p[N],lmax[N],rmax[N]; int init() {n=strlen(s+1);for(int i=2*n;i;i-=2){s[i]=s[i/2];s[i-1]='*';}s[2*n+1]='*';s[0]='@',s[2*n+2]='&';//哨兵return 2*n+1; } int manacher() {int res=0;int now=0,mx=0;for(int i=1;i<=n;i++){p[i]=i<mx?min(p[2*now-i],mx-i):1;while(s[i+p[i]]==s[i-p[i]]) p[i]++;if(i+p[i]>mx){mx=i+p[i];now=i;}res=max(res,p[i]-1);}return res; } int main() {cin>>s+1;n=init();manacher();for(int i=1;i<=n;i++){int r=p[i]+i-1;rmax[r]=max(rmax[r],p[i]-1);}for(int i=n;i;i--){int l=i-p[i]+1;lmax[l]=max(lmax[l],p[i]-1);}for(int i=1;i<=n;i++) rmax[i]=max(rmax[i-1],rmax[i]);for(int i=n;i>=1;i--) lmax[i]=max(lmax[i+1],lmax[i]);int res=0;int ok=0;// 特判整個字符串都是回文串for(int i=1;i<=n;i++) if(p[i]-1==(n-1)/2) ok=1;if(ok) cout<<(n-1)/2-1<<'\n';else {for(int i=1;i<=n;i++) res=max(res,lmax[i]+rmax[i]);cout<<res<<'\n';}return 0; }

E - 劃分樹

大佬題解

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0) #pragma GCC optimize(2) #include<cstring> #include<iostream> #include<algorithm> using namespace std; typedef long long ll; typedef pair<int,int> pii; const int N=500010; const ll mod=1004535809; int h[N],e[2*N],ne[2*N],idx; int n,m; ll w[N]; ll f[N][2]; void add(int a,int b) {e[idx]=b;ne[idx]=h[a];h[a]=idx++; } void dfs(int u) {f[u][0]=1;//刪除偶數(shù)條邊(不刪)方案數(shù)是1ll cnt1,cnt0;for(int i=h[u];i!=-1;i=ne[i]){int j=e[i];dfs(j);w[u]^=w[j];cnt0=f[u][0],cnt1=f[u][1];f[u][0]=(cnt0*f[j][0]+cnt1*f[j][1])%mod;f[u][1]=(cnt1*f[j][0]+cnt0*f[j][1])%mod;}cnt0=f[u][0],cnt1=f[u][1];if(u==1) return;// 考慮連向父親if(w[u]==0) f[u][0]=(f[u][0]+cnt1)%mod;if(w[u]==m) f[u][1]=(f[u][1]+cnt0)%mod;} int main() {IO;int T=1;//cin>>T;while(T--){cin>>n>>m;memset(h,-1,sizeof h);for(int i=2;i<=n;i++){int p;cin>>p;add(p,i);}for(int i=1;i<=n;i++) cin>>w[i];dfs(1);cout<<(f[1][0]*(w[1]==m)+f[1][1]*(w[1]==0))%mod<<'\n';}return 0;}

F有點懵,先記下來。
要加油哦~

總結(jié)

以上是生活随笔為你收集整理的牛客练习赛 57——manacher算法 树形dp?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。