Codeforces Round #310 (Div. 2)
Problem A:
題目大意:給你一個由0,1組成的字符串,如果有相鄰的0和1要消去,問你最後還剩幾個字符。
寫的時候不想看題意直接看樣例,結果我以為是1在前0在後才行,交上去錯了。。後來仔細
看了看,哎。以後不能自以為是啊。
#include<bits/stdc++.h> using namespace std; const int N=2*1e5+2; char s[N]; bool vis[N]; int main() { int n; scanf("%d%s",&n,s); int cnt=n; int cnt1=0,cnt0=0;View Codefor(int i=0;i<n;i++) { if(s[i]==‘0‘) cnt0++; else cnt1++; } printf("%d\n",max(cnt0-cnt1,cnt1-cnt0)); }
Problem B:
題目大意:給你n個一排的齒輪,每個齒輪有編號(0->n-1)的鋸齒,問你能不能轉動第一個輪子,
使其向上的鋸齒依次為,0,1,2,3...n-1。水題,你就把第一個齒輪轉到0的次數記錄下來,第偶數
個加上,奇數個減去,判斷一下。
#include<bits/stdc++.h> usingView Codenamespace std; const int N=1005; int a[N]; int main() { int n; cin>>n; for(int i=0;i<n;i++) scanf("%d",&a[i]); int cnt=n-a[0]; //printf("%d\n",cnt); for(int i=1;i<n;i++) { if(i%2) { if((a[i]-cnt+n)%n!=i) { puts("No"); return 0; } } else { if((a[i]+cnt+n)%n!=i) { puts("No"); return 0; } } } puts("Yes"); return 0; }
Problem C:
題目大意:給你n個編號1->n的杯子,編號代表了它們的大小,只有大的能套在小的上,現在
給你這些杯子現在的情況,讓你把他變成1<-2<-3<-4....<-n這種形式需要操作幾次。簡單模擬
一下就好了。
#include<bits/stdc++.h> using namespace std; int n,k,ans,st; int pre[100005]; void Find(int x) { if(pre[x]!=x) { Find(pre[x]); ans++; pre[x]=x; } } void judge(int now,int p) { if(now==p+1 || p==-1) { st=now; judge(pre[now],now); } } int main() { cin>>n>>k; for(int i=1;i<=n;i++) pre[i]=i; for(int i=1;i<=k;i++) { int m; scanf("%d",&m); int p=-1; while(m--) { int g; scanf("%d",&g); if(p!=-1) { pre[p]=g; } p=g; } } ans=0; st=1; judge(1,-1); Find(st); for(int i=st+1;i<=n;i++) { Find(i); pre[i-1]=i; ans++; } cout<<ans<<endl; return 0; }View Code
Problem D:
題目大意:有n個排成以行的小道他們的範圍分別是(l[i]->r[i])且l[i+1]>r[i],現在有m個長度為b[i]的橋
兩個島能加上長度為a的橋當且僅當 r[i+1]-l[i]>=a>=l[i+1]-r[i]。問你能不能完成這個工作。
這個題很顯然,可以轉換成這個問題:有n-1個區間,m個數,每個數最多只能用一次,第i個數只
要能被第j個區間包含,那麽這個數就可以放入這個區間內。求出,當所有區間裏都恰有一個數時的情況。
我寫的時候一直在想固定最大範圍和最小範圍來貪心,用橋去滿足他們,這種方法是不對的。
思路:我們可以將區間按按l排序,橋按長度排序,然後將當前滿足 r>=a>=l 的區間都加到優先隊列
裏面,每次取出r最小的區間,這個橋就搭在這個區間上,為什麽呢,因為對於優先隊列裏面的區間
來說,當前及以後的橋都滿足,len[i]>=l 所以可以不用考慮區間的l,這樣我們顯然就可以貪心地取
r小的區間。
#include<bits/stdc++.h> #define ll long long using namespace std; const int N=2*1e5+5; struct node { ll mx,mn; int id; bool operator <(const node&t) const { return mx>t.mx; } }w[N]; bool cmp(node a,node b) { return a.mn<b.mn; } struct num { ll v; int id; bool operator <(const num &t)const { return v<t.v; } }a[N]; ll ans[N]; int n,m; int main() { cin>>n>>m; ll pl=-1,pr=-1; for(int i=0;i<n;i++) { ll l,r; scanf("%I64d%I64d",&l,&r); if(pl!=-1) { //printf("%d**\n",i); w[i].mx=r-pl; w[i].mn=l-pr; w[i].id=i; } pl=l,pr=r; } for(int i=1;i<=m;i++) { scanf("%I64d",&a[i].v); a[i].id=i; } sort(a+1,a+1+m); sort(w+1,w+n,cmp); //for(int i=1;i<=m;i++) printf("%I64d ",a[i].v); //puts(""); //for(int i=1;i<n;i++) printf("[%I64d,%I64d] ",w[i].mn,w[i].mx); priority_queue<node> Q; int cnt=0; for(int i=1,j=1;i<=m;i++) { while(w[j].mn<=a[i].v && a[i].v<=w[j].mx && j<n) { Q.push(w[j]); j++; } if(Q.empty()) continue; node now=Q.top();Q.pop(); if(a[i].v>now.mx) { puts("No"); return 0; } ans[now.id]=a[i].id; cnt++; } //printf("%d\n",cnt); if(cnt<n-1) { puts("No"); return 0; } puts("Yes"); for(int i=1;i<n;i++) printf("%I64d%c",ans[i],i==n-1?‘\n‘ : ‘ ‘); return 0; }View Code
problem E:
題意:
有一塊n*n大小的巧克力,n<=1e9。現在進行操作,每次都從反對角線上選擇一點,然後往上或往左一直吃,
每當到達巧克力邊緣或者下一塊已經被吃了,則停止。問你每次操作能吃到幾塊巧克力。
思維題,感覺挺難想到了,還是我太菜了。。
思路:我們考慮從j列往上吃巧克力,吃掉的個數受什麽影響呢,肯定不受<j的列印象,對它有直接影響的就
他右邊第一個有操作的點,如果這個點的操作時向左吃,則從j列向上吃只能吃到有操作點的那一行,如果右邊
第一個有操作的點是向上吃,則j列吃的和它一樣。
#include<bits/stdc++.h> using namespace std; map<int,int> u,l; int n,q; int main() { cin>>n>>q; while(q--) { int x,y; char s[3]; scanf("%d%d%s",&x,&y,s); map<int,int>::iterator p; if(s[0]==‘U‘) { int ans=0; p=u.lower_bound(x); if(u.count(x)) { puts("0"); continue; } if(p==u.end()) ans=y; else ans=y-(p->second); printf("%d\n",ans); l[y]=x; u[x]=y-ans; } else { int ans=0; p=l.lower_bound(y); if(l.count(y)) { puts("0"); continue; } if(p==l.end()) ans=x; else ans=x-(p->second); printf("%d\n",ans); u[x]=y; l[y]=x-ans; } } return 0; }View Code
Codeforces Round #310 (Div. 2)