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

歡迎訪問(wèn) 生活随笔!

生活随笔

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

编程问答

牛客练习赛 67——ST表

發(fā)布時(shí)間:2023/12/3 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 牛客练习赛 67——ST表 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

A.牛牛愛(ài)字符串

注意原字符串有空格,不要用cin

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0) #pragma GCC optimize(2) #include<string> #include<iostream> #include<algorithm> using namespace std; int main() {IO;int T=1;//cin>>T;while(T--){string s;while(getline(cin,s)){vector<string> ans;int n=s.size();for(int i=0;i<n;i++){if(s[i]<'0'||s[i]>'9') continue;string now="";while(i<n&&s[i]>='0'&&s[i]<='9'){now+=s[i];i++;}reverse(now.begin(),now.end());while(now.size()>1&&now.back()=='0') now.pop_back();reverse(now.begin(),now.end());ans.push_back(now);} for(auto t:ans) cout<<t<<' ';cout<<'\n';}}return 0; }

B.牛牛愛(ài)位運(yùn)算

&只會(huì)越運(yùn)算越小,直接選擇最大的數(shù)即可

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0) #pragma GCC optimize(2) #include<string> #include<iostream> #include<algorithm> using namespace std; const int N=100010; int a[N],n; int main() {IO;int T=1;cin>>T;while(T--){cin>>n;for(int i=1;i<=n;i++) cin>>a[i];sort(a+1,a+1+n);cout<<a[n]<<'\n';}return 0; }

C.牛牛愛(ài)博弈

打表找規(guī)律,懂得都懂
最終只要nnn不是333的倍數(shù)先手必勝

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0) #pragma GCC optimize(2) #include<cstring> #include<iostream> #include<algorithm> #include<unordered_set> using namespace std; const int N=110; int sg[N]; // int dfs(int u) // { // if(sg[u]!=-1) return sg[u]; // unordered_set<int> mp; // for(int i=0;(1<<i)<=u;i++) mp.insert(dfs(u-(1<<i)));// for(int i=0;;i++) // if(!mp.count(i)) return sg[u]=i; // } int main() {IO;int T=1;cin>>T;memset(sg,-1,sizeof sg);while(T--){cin>>n;if(n%3) cout<<"Alan\n";else cout<<"Frame\n";}// for(int i=0;i<=100;i++)// {// cout<<i<<' ';// if(dfs(i)) cout<<"Alan\n";// else cout<<"Frame\n";// }return 0; }

D. 牛妹愛(ài)數(shù)列

f[i][0/1]f[i][0/1]f[i][0/1]表示:考慮前iii個(gè)序列,把他們?nèi)兂?span id="ozvdkddzhkzd" class="katex--inline">0/10/10/1的最小翻轉(zhuǎn)次數(shù)
轉(zhuǎn)移:考慮最后一步是單點(diǎn)修改還是前綴修改。
如果是單點(diǎn)修改f[i][1]=min(f[i][1],f[i?1][1]+1?a[i]),f[i][0]=min(f[i][0],f[i?1][0]+a[i])f[i][1]=min(f[i][1],f[i-1][1]+1-a[i]),f[i][0]=min(f[i][0],f[i-1][0]+a[i])f[i][1]=min(f[i][1],f[i?1][1]+1?a[i]),f[i][0]=min(f[i][0],f[i?1][0]+a[i])
如果是前綴修改f[i][1]=min(f[i][1],f[i?1][0]+a[i]+1),f[i][0]=min(f[i][0],f[i?1][1]+1?a[i]+1)f[i][1]=min(f[i][1],f[i-1][0]+a[i]+1),f[i][0]=min(f[i][0],f[i-1][1]+1-a[i]+1)f[i][1]=min(f[i][1],f[i?1][0]+a[i]+1),f[i][0]=min(f[i][0],f[i?1][1]+1?a[i]+1)

#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=100010; int f[N][2]; int a[N],n; int main() {IO;int T=1;//cin>>T;while(T--){cin>>n;for(int i=1;i<=n;i++) cin>>a[i];memset(f,0x3f,sizeof f);f[0][0]=f[0][1]=0;for(int i=1;i<=n;i++){f[i][0]=min(f[i-1][0]+a[i],f[i-1][1]+1-a[i]+1);f[i][1]=min(f[i-1][0]+1-a[i]+1,f[i-1][1]+1-a[i]);}cout<<f[n][0]<<'\n';}return 0; }

E.牛妹游歷城市

暴力建圖邊數(shù)達(dá)到恐怖的n2n^2n2不光空間開(kāi)不下,而且時(shí)間跑不過(guò),不可取。
考慮優(yōu)化建圖:建立323232個(gè)虛擬源點(diǎn)(編號(hào)n+1…n+32)n+1 \dots n+32)n+1n+32)如果一個(gè)點(diǎn)iiiaia_iai?的二進(jìn)制表示中第j(0≤j≤31)j(0\leq j\leq 31)j(0j31)位是1,那么連一條邊i?>n+j+1i->n+j+1i?>n+j+1權(quán)值是1<<j1<<j1<<j的邊,并且連一條n+j+1?>in+j+1->in+j+1?>i權(quán)值是000的邊。然后不難發(fā)現(xiàn)原圖中的所有邊都可以轉(zhuǎn)化成新圖的邊,同樣新圖的所有邊都能轉(zhuǎn)化成原圖的邊。 但是并不影響求最短路比如權(quán)值是101011和101010的兩個(gè)點(diǎn),我們會(huì)建立邊權(quán)是10、1000、100000這些路徑,但是發(fā)現(xiàn)這些相當(dāng)于重邊,不會(huì)影響答案。
博主的圖非常清楚直接秒懂

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0) #pragma GCC optimize(2) #include<queue> #include<cstring> #include<iostream> #include<algorithm> using namespace std; typedef long long ll; typedef pair<ll,int> pli; const int N=111010,M=1000010; const ll INF=0x3f3f3f3f3f3f3f3f; int h[N],e[M],ne[M],idx; ll w[M],a[N]; ll dist[N]; bool st[N]; int n; void add(int a,int b,ll c) {e[idx]=b;w[idx]=c;ne[idx]=h[a];h[a]=idx++; } void dijkstra() {memset(dist,0x3f,sizeof dist);memset(st,0,sizeof st);dist[1]=0;priority_queue<pli,vector<pli>,greater<pli>> q;q.push({0,1});while(q.size()){int t=q.top().second;q.pop();if(st[t]) continue;st[t]=1;for(int i=h[t];i!=-1;i=ne[i]){int j=e[i];if(dist[j]>dist[t]+w[i]){dist[j]=dist[t]+w[i];q.push({dist[j],j});}}} } int main() {IO;int T=1;cin>>T;while(T--){cin>>n;memset(h,-1,sizeof h);idx=0;for(int i=1;i<=n;i++) cin>>a[i];for(int i=1;i<=n;i++)for(int j=0;j<32;j++)if(a[i]>>j&1){add(i,j+n+1,1ll<<j);add(j+n+1,i,0ll);}dijkstra();if(dist[n]==INF) cout<<"Impossible\n";else cout<<dist[n]<<'\n';}return 0; }

學(xué)習(xí)ST表,F明天補(bǔ)了

F.牛妹的蘋(píng)果樹(shù)

方法一:線段樹(shù)(動(dòng)態(tài))+歐拉序ST表求lca
首先有一個(gè)引理:樹(shù)的直徑具有可合并的性質(zhì),同一棵樹(shù)上兩個(gè)區(qū)間的直徑的兩個(gè)端點(diǎn)分別為 (a,b)(a,b)(a,b)(c,d)(c,d)(c,d),那么合并兩個(gè)區(qū)間后的新的直徑的端點(diǎn)一定在a,b,c,d{a,b,c,d}a,b,c,d中,通過(guò)枚舉端點(diǎn)計(jì)算它們的距離(6種情況),取最大值可以得到兩個(gè)區(qū)間合并的直徑。 其正確性證明和兩遍dfs求樹(shù)的直徑的證明過(guò)程類(lèi)似。
由此我們考慮線段樹(shù)維護(hù)區(qū)間直徑即可。求lca最好用歐拉序+ST表的,這個(gè)我不會(huì)可以借鑒大佬寫(xiě)法線段樹(shù)+ST表求lca
方法二:ST表維護(hù)直徑(靜態(tài))+ST表求lca
由于本題為區(qū)間靜態(tài)問(wèn)題,并且直徑有區(qū)間可重復(fù)計(jì)算的性質(zhì),考慮用ST表維護(hù)直徑ST表維護(hù)直徑

// O(nlogn) #include<iostream> #include<algorithm> #include<cstring> #define x first #define y second using namespace std; typedef long long ll; typedef pair<int,int> pii; const int N=300010,M=2*N; int h[N],e[M],ne[M],idx; ll w[M]; ll dist[N]; int dfn[N],eular[M],ST[M][20],cnt; int lg[M]; pii f[N][20]; int n,q; void add(int a,int b,ll c) {e[idx]=b;w[idx]=c;ne[idx]=h[a];h[a]=idx++; }void dfs(int u,int fa) {dfn[u]=++cnt;ST[cnt][0]=u;f[u][0]={u,u};for(int i=h[u];i!=-1;i=ne[i]){int j=e[i];if(j==fa) continue;dist[j]=dist[u]+w[i];dfs(j,u);ST[++cnt][0]=u;} } int lca(int a,int b) {a=dfn[a],b=dfn[b];if(a>b) swap(a,b);int len=lg[b-a+1];return dist[ST[a][len]]<dist[ST[b-(1<<len)+1][len]]?ST[a][len]:ST[b-(1<<len)+1][len]; } ll calc(int a,int b) {int pab=lca(a,b);return dist[a]+dist[b]-2*dist[pab]; } void pre() {for(int i=2;i<=cnt;i++) lg[i]=lg[i>>1]+1;for(int j=1;j<=lg[cnt];j++)for(int i=1;i+(1<<j)-1<=cnt;i++)ST[i][j]=dist[ST[i][j-1]]<dist[ST[i+(1<<j-1)][j-1]]?ST[i][j-1]:ST[i+(1<<j-1)][j-1];for(int j=1;j<=lg[n];j++)for(int i=1;i+(1<<j)-1<=n;i++){pii a=f[i][j-1],b=f[i+(1<<j-1)][j-1];f[i][j]={a.x,a.y};if(calc(a.x,b.x)>calc(f[i][j].x,f[i][j].y)) f[i][j]={a.x,b.x};if(calc(a.x,b.y)>calc(f[i][j].x,f[i][j].y)) f[i][j]={a.x,b.y};if(calc(a.y,b.x)>calc(f[i][j].x,f[i][j].y)) f[i][j]={a.y,b.x};if(calc(a.y,b.y)>calc(f[i][j].x,f[i][j].y)) f[i][j]={a.y,b.y};if(calc(b.x,b.y)>calc(f[i][j].x,f[i][j].y)) f[i][j]={b.x,b.y};} } ll query(int l,int r) {int len=lg[r-l+1];pii a=f[l][len],b=f[r-(1<<len)+1][len];ll res=calc(a.x,a.y);res=max(res,calc(a.x,b.x));res=max(res,calc(a.x,b.y));res=max(res,calc(a.y,b.x));res=max(res,calc(a.y,b.y));res=max(res,calc(b.x,b.y));return res; } int main() {memset(h,-1,sizeof h);cin>>n>>q;for(int i=1;i<n;i++){int a,b;ll c;cin>>a>>b>>c;add(a,b,c),add(b,a,c);}dfs(1,0);pre();while(q--){int l,r;cin>>l>>r;cout<<query(l,r)<<'\n';}return 0; }

總結(jié)

以上是生活随笔為你收集整理的牛客练习赛 67——ST表的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

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