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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Codeforces Round #661 (Div. 3)

發布時間:2023/12/3 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Codeforces Round #661 (Div. 3) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

A - Remove Smallest

排個序,如果相鄰的數大于一就不滿足題意

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0) #define debug(x) cout<<#x<<": "<<x<<" " #include<iostream> #include<algorithm> #include<cstring> using namespace std; typedef long long ll; const int N=110; int a[N]; int main() {IO;int T;cin>>T;while(T--){int n;cin>>n;for(int i=0;i<n;i++) cin>>a[i];sort(a,a+n);bool ok=1;for(int i=0;i<n-1;i++)if(a[i+1]>a[i]+1) {ok=0;break;}if(ok) cout<<"YES"<<endl;else cout<<"NO"<<endl;}return 0; }

B - Gifts Fixing

禮物最終個數肯定是最小的那個。每個禮物減小到最少的那個,注意可以同時減少兩種禮物。

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0) #define debug(x) cout<<#x<<": "<<x<<" " #include<iostream> #include<algorithm> #include<cstring> using namespace std; typedef long long ll; const int N=110; ll a[N],b[N]; int main() {IO;int T;cin>>T;while(T--){int n;cin>>n;ll mina=2e9;ll minb=2e9;for(int i=0;i<n;i++) {cin>>a[i];mina=min(mina,a[i]);}for(int i=0;i<n;i++){cin>>b[i];minb=min(minb,b[i]);}ll res=0;for(int i=0;i<n;i++) res+=max(a[i]-mina,b[i]-minb);cout<<res<<endl;}return 0; }

C - Boats Competition

枚舉+雙指針
由于體重非常小,兩兩配對的體重和也很小,直接暴力枚舉兩兩體重和w。現在問題轉化成原序列找出兩個數的和等于w,雙指針。

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0) #define debug(x) cout<<#x<<": "<<x<<" " #include<iostream> #include<algorithm> #include<cstring> using namespace std; typedef long long ll; const int N=110; int a[N],n; int main() {IO;int T;cin>>T;while(T--){cin>>n;for(int i=1;i<=n;i++) cin>>a[i];if(n==1) {cout<<0<<endl;continue;}sort(a+1,a+n+1);int res=0,mx=0;for(int w=a[1]+a[2];w<=a[n-1]+a[n];w++){int cnt=0;for(int i=1,j=n;i<j;i++){while(j>i&&a[i]+a[j]>w) j--;if(j<=i) break; //注意這點 因為這wa了一次if(a[i]+a[j]==w) cnt++,j--;}res=max(res,cnt);}cout<<res<<endl;}return 0; }

D - Binary String To Subsequences

貪心+二分
貪心:如果該位是1那么找一個末尾是0的序列放進去如果不存在那么新添一組
比如目前有五組0 0 1 1 1分別表示該組最后一個字符是0或者1,如果該位是1我們就二分出最后一個0,pos=2,組別表示變成0 1 1 1 1。如果該位使0我們二分處第一個1的位置,pos=3,組別表示變成0 0 0 1 1,這樣操作可以發現組別表示的序列始終是有序的,保證時間復雜度為O(nlogn)O(nlogn)O(nlogn)
好像有O(n)O(n)O(n)的做法奈何wctl,寫題的時候只想到這個做法。

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0) #define debug(x) cout<<#x<<": "<<x<<" " #include<iostream> #include<algorithm> #include<cstring> #include<string> using namespace std; typedef long long ll; const int N=200010; int pos[N],a[N]; int main() {IO;int T;cin>>T;while(T--){int n;string s;cin>>n>>s;int cnt=1;a[1]=s[0]-'0';pos[0]=1;for(int i=1;i<n;i++){int t=s[i]-'0';if(t){int l=1,r=cnt;while(l<r){int mid=l+r+1>>1;if(a[mid]<=0) l=mid;else r=mid-1;}if(a[l]==0){a[l]=1;pos[i]=l;}else {a[++cnt]=1;pos[i]=cnt;}}else{int l=1,r=cnt;while(l<r){int mid=l+r>>1;if(a[mid]>=1) r=mid;else l=mid+1;}if(a[l]==1){a[l]=0;pos[i]=l;}else {a[++cnt]=0;pos[i]=cnt;}}}cout<<cnt<<endl;for(int i=0;i<n;i++) cout<<pos[i]<<" ";cout<<endl;}return 0; }

這次做了4個題,差一點做出了E1。

E1 - Weights Division (easy version)

我沒想到這次我不在意的點就是這題的關鍵的!!!
先dfs一下把從根節點到每個葉子節點每條邊跑的次數記錄一下,記作cnt[i],如果該邊邊權為w[i]如果把這條邊砍一半,那么總的路程減小(w[i]-w[i]/2)*cnt[i],顯然貪心,用個優先隊列(按照減小的多優先級高)維護一下就行了。
坑點:很容易想到按照w[i]*cnt[i]排序,不過這題下取整導致問題不斷。(我做的時候想這題應該不會那么麻煩,就圖個省事結果。。。)

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0) #define debug(x) cout<<#x<<": "<<x<<" " #include<iostream> #include<algorithm> #include<cstring> #include<string> #include<queue> #include<vector> using namespace std; typedef long long ll; const int N=100010,M=400010; int h[N],e[M],ne[M],idx; ll w[M],limit,res; int n,d[N],cnt[M]; struct node {ll w;int num;bool operator <(const node&o)const{ll sub1=(w-w/2)*num;ll sub2=(o.w-o.w/2)*o.num;return sub1<sub2;//其實也可以直接 return (w+1)/2*num<(o.w+1)/2*o.num; 上去整} }; priority_queue<node> q;void add(int a,int b,ll c) {e[idx]=b;w[idx]=c;ne[idx]=h[a];h[a]=idx++;d[b]++;//統計度數,度數為1是葉子節點 } int dfs(int u,int fa) {int lcnt=0;for(int i=h[u];i!=-1;i=ne[i]){int j=e[i];if(j==fa) continue;cnt[i]+=(d[j]==1);cnt[i]+=dfs(j,u);lcnt+=cnt[i];}return lcnt; } void init() {for(int i=0;i<=n;i++) h[i]=-1,d[i]=0,cnt[i]=0,cnt[i+n]=0;idx=res=0;while(q.size()) q.pop(); } int main() {IO;int T;cin>>T;while(T--){cin>>n>>limit;init();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,-1);for(int i=0;i<2*n-2;i+=2) {q.push({w[i],cnt[i]+cnt[i+1]});res+=w[i]*(cnt[i]+cnt[i+1]);}ll ans=0;while(res>limit){auto t=q.top();q.pop();q.push({t.w/2,t.num});res-=1ll*(t.w-t.w/2)*t.num;ans++;}cout<<ans<<endl;}return 0; }

E2 - Weights Division (hard version)

E1砍邊都是花費1代價,而E2就是有些邊砍一半需要花費1代價有些2代價。顯然我們考慮用兩個優先隊列維護q1,q2,q1維護花費1代價的 q2維護花費2代價的。仍然貪心。每次考慮花費1代價砍邊,如果發現花兩次1代價減小的路程小于直接花費2代價砍邊減小的路程,那么就直接花費2代價砍邊。

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0) #define debug(x) cout<<#x<<": "<<x<<" " #include<iostream> #include<algorithm> #include<cstring> #include<string> #include<queue> #include<vector> using namespace std; typedef long long ll; const int N=100010,M=200010; int h[N],e[M],ne[M],idx,cost[M]; ll w[M],limit,res; int n,d[N],cnt[M]; struct node {ll w;int num;bool operator <(const node&o)const{ll sub1=(w-w/2)*num;ll sub2=(o.w-o.w/2)*o.num;return sub1<sub2;} }; priority_queue<node> q1,q2; void add(int a,int b,ll c,int coin) {e[idx]=b;w[idx]=c;cost[idx]=coin;ne[idx]=h[a];h[a]=idx++;d[b]++; } int dfs(int u,int fa) {int lcnt=0;for(int i=h[u];i!=-1;i=ne[i]){int j=e[i];if(j==fa) continue;cnt[i]+=(d[j]==1);cnt[i]+=dfs(j,u);lcnt+=cnt[i];}return lcnt; } void init() {for(int i=0;i<=n;i++) h[i]=-1,d[i]=0,cnt[i]=0,cnt[i+n]=0;idx=res=0;while(q1.size()) q1.pop();while(q2.size()) q2.pop();q1.push({0,0}),q1.push({0,0}),q2.push({0,0});//哨兵,避免很多邊界情況。 } int main() {IO;int T;cin>>T;while(T--){cin>>n>>limit;init();for(int i=1;i<n;i++){int a,b,coin;ll c;cin>>a>>b>>c>>coin;add(a,b,c,coin);add(b,a,c,coin);}dfs(1,-1);for(int i=0;i<2*n-2;i+=2) {if(cost[i]==1) q1.push({w[i],cnt[i]+cnt[i+1]});else q2.push({w[i],cnt[i]+cnt[i+1]});res+=w[i]*(cnt[i]+cnt[i+1]);}ll ans=0;while(res>limit){auto a=q1.top();q1.pop();auto b=q1.top();q1.pop();auto c=q2.top();q2.pop();ll suba=(a.w-a.w/2)*a.num;ll subb=max((a.w/2-a.w/4)*a.num,(b.w-b.w/2)*b.num);ll subc=(c.w-c.w/2)*c.num;if(res-suba<=limit) {ans++;break;}else {if(suba+subb<=subc){res-=subc;q1.push(a),q1.push(b);q2.push({c.w/2,c.num});ans+=2;}else{res-=suba;q1.push(b),q1.push({a.w/2,a.num});q2.push(c);ans++;}}}cout<<ans<<endl;}return 0; }

注意:每次只考慮花費1代價砍邊
我在寫的時候寫了一份每次考慮花費2代價砍邊。比較兩次1代價和一次2代價減小的路程嗎,這樣貪心其實不正確,非常dt。
下面代碼是錯誤的貪心思路每次考慮花費2代價砍邊

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0) #define debug(x) cout<<#x<<": "<<x<<" " #include<iostream> #include<algorithm> #include<cstring> #include<string> #include<queue> #include<vector> using namespace std; typedef long long ll; const int N=100010,M=400010; int h[N],e[M],ne[M],idx,cost[M]; ll w[M],limit,res; int n,d[N],cnt[M]; struct node {ll w;int num;bool operator <(const node&o)const{ll sub1=(w-w/2)*num;ll sub2=(o.w-o.w/2)*o.num;return sub1<sub2;} }; priority_queue<node> q1,q2;void add(int a,int b,ll c,int coin) {e[idx]=b;w[idx]=c;cost[idx]=coin;ne[idx]=h[a];h[a]=idx++;d[b]++; } int dfs(int u,int fa) {int lcnt=0;for(int i=h[u];i!=-1;i=ne[i]){int j=e[i];if(j==fa) continue;cnt[i]+=(d[j]==1);cnt[i]+=dfs(j,u);lcnt+=cnt[i];}return lcnt; } void init() {for(int i=0;i<=n;i++) h[i]=-1,d[i]=0,cnt[i]=0,cnt[i+n]=0;idx=res=0;while(q1.size()) q1.pop();while(q2.size()) q2.pop(); } int main() {IO;int T;cin>>T;while(T--){cin>>n>>limit;init();for(int i=1;i<n;i++){int a,b,coin;ll c;cin>>a>>b>>c>>coin;add(a,b,c,coin);add(b,a,c,coin);}dfs(1,-1);for(int i=0;i<2*n-2;i+=2) {if(cost[i]==1) q1.push({w[i],cnt[i]+cnt[i+1]});else q2.push({w[i],cnt[i]+cnt[i+1]});res+=w[i]*(cnt[i]+cnt[i+1]);}q1.push({0,0}),q1.push({0,0}),q2.push({0,0});ll ans=0;while(res>limit){auto a=q1.top();q1.pop();auto b=q1.top();q1.pop();auto c=q2.top();q2.pop();ll suba1=(a.w-a.w/2)*a.num;ll suba2=(a.w/2-a.w/4)*a.num;ll subb=(b.w-b.w/2)*b.num;ll subc=(c.w-c.w/2)*c.num;if(res-suba1<=limit) {ans++;break;}else if(res-suba1-max(suba2,subb)<=limit||res-subc<=limit) {ans+=2;break;}else if(res-suba1-subc<=limit) {ans+=3;break;}else {if(suba2>subb){if(suba1+suba2>subc){res-=suba1+suba2;q1.push(b),q1.push({a.w/4,a.num});q2.push(c);}else{res-=subc;q1.push(a),q1.push(b);q2.push({c.w/2,c.num});}}else{if(suba1+subb>subc){res-=suba1+subb;q1.push({b.w/2,b.num}),q1.push({a.w/2,a.num});q2.push(c);}else{res-=subc;q1.push(a),q1.push(b);q2.push({c.w/2,c.num});}}ans+=2;}}cout<<ans<<endl;}return 0; }

嘻嘻還是div3能上一點分QvQ,希望今天div2掉少點分(div2日常掉分)-。-,要加油哦~

總結

以上是生活随笔為你收集整理的Codeforces Round #661 (Div. 3)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。