Codeforces Round #661 (Div. 3)(A->D)
A:http://codeforces.com/contest/1399/problem/A
解析:
不多說了,直接sort,判是否存在相鄰差>1
#include<iostream> #include<cstring> #include<algorithm> #include<stack> using namespace std; typedef long long ll; const int maxn=60; int l[maxn],r[maxn]; char ch[3*maxn]; int a[maxn]; int pos[maxn]; int main() {int t; cin>>t; while(t--) { int n; cin>>n; for(int i=1;i<=n;i++) cin>>a[i]; if(n==1) { cout<<"YES"<<endl;continue; } sort(a+1,a+1+n); int ok=0; for(int i=2;i<=n;i++)if(abs(a[i]-a[i-1])>1) { ok=1;break; } if(ok) cout<<"NO"<<endl; else cout<<"YES"<<endl; } }
B:http://codeforces.com/contest/1399/problem/B
題意:
長度為n的a[]和b[]
三種操作:
1. ai--
2. bi--
3. ai和bi同時減1
分別把a[]和b[]變成全相等陣列,問最少需要的運算元。a[]不一定要和b[]相等。
解析:
因為只存在自減操作,所以元素並不會增大。所以最少需要的操作,一定是a[]和b[]變成對應的最小值。
所以先找到各自的最小值。
遍歷a[]和b[],對於每一個ai,bi,算出倆差值,先同時減,然後較大的再自減就可以了。
#include<iostream> #include<cstring> #include<algorithm> #include<stack> #include<map> using namespace std; typedef long long ll; const int maxn=60; const int mod=1e9+7; int l[maxn],r[maxn]; char ch[3*maxn]; ll a[maxn]; ll b[maxn]; ll c[maxn],d[maxn]; int pos[maxn]; int main() { int t; cin>>t; while(t--) { int n; cin>>n; map<ll,ll>m1; map<ll,ll>m2; int tot1=0,tot2=0; ll mina=mod,minb=mod; for(int i=1;i<=n;i++) { cin>>a[i]; mina=min(a[i],mina); } for(int i=1;i<=n;i++) { cin>>b[i]; minb=min(b[i],minb); } ll cnt=0; for(int i=1;i<=n;i++) { int m1=a[i]-mina; int m2=b[i]-minb; if(m1>m2) { cnt+=m2; cnt+=m1-m2; } if(m1==m2) cnt+=m1; if(m1<m2) { cnt+=m1; cnt+=m2-m1; } } cout<<cnt<<endl; } }
C:http://codeforces.com/contest/1399/problem/C
題意:
有n個人想參加划船比賽。第i個參與者的權重是wi。
只有兩人組成的團隊可以參加比賽。
如果有k個團隊(a1,b1),(a2,b2),…,(ak,bk),其中ai是第i個團隊的第一個參與者的權重,bi是第二個團隊的權重第i個團隊的參與者,則必須滿足條件a1 + b1 = a2 + b2 =⋯= ak + bk = s,其中s是每個團隊的總權重。問有多少個團隊可以參賽。
解析:
n==50,直接三重for暴力遍歷每一個和值即可。
先統計不同的兩兩和,然後對它們進行暴力列舉,看每一個值能組成多少團隊,取最大即可。
#include<iostream> #include<cstring> #include<algorithm> #include<stack> #include<map> using namespace std; typedef long long ll; const int maxn=60; const int mod=1e9+7; int l[maxn],r[maxn]; char ch[3*maxn]; int a[maxn]; int b[8*maxn]; int vis[maxn]; ll c[maxn],d[maxn]; int pos[maxn]; int main() { int t; cin>>t; while(t--) { memset(vis,0,sizeof(vis)); int n; cin>>n; for(int i=1;i<=n;i++) { cin>>a[i]; } int tot=0; map<int,int>m1; for(int i=1;i<=n;i++) { for(int j=i+1;j<=n;j++) { int md=a[i]+a[j]; if(!m1[md]) b[tot++]=md; m1[md]=1; } } int maxx=0; for(int i=0;i<tot;i++) { memset(vis,0,sizeof(vis)); int cnt=0; int md=b[i]; for(int j=1;j<=n;j++) { for(int c=j+1;c<=n;c++) { int md2=a[j]+a[c]; if(!vis[j]&&!vis[c]&&md2==md) { cnt++; vis[j]=1; vis[c]=1; } } } maxx=max(maxx,cnt); } cout<<maxx<<endl; } }
D:http://codeforces.com/contest/1399/problem/D
題意:
給定一個字串由0/1組成,問最少有幾個字串是01間隔的(010101……或者101010……)。輸出最少的個數和每個字元在第幾個子字串。
解析:
是存在貪心思想的。
因為要想個數更少,肯定對於遍歷到的每個0,要接到它之前已經存在的0101...上,而不是另開一個新子串,只有之前沒得接的時候,才需要另開新子串。
用到兩個佇列,一個是stack st[2],用來存以0/1結尾的符合條件的子序列編號。
vector用來存每個字元屬於第幾個子串。
接下來看註釋吧:
#include<iostream> #include<stack> #include<vector> using namespace std; typedef long long ll; int main() { int t; cin>>t; while(t--) { int n; cin>>n; string s; cin>>s; stack<int>st[2]; vector<int>vv; int len=s.length(); int all=1; for(int i=0;i<len;i++) { int now=s[i]-'0'; if(st[now^1].empty()) //now對應的字元,如果沒得接,就新開一個子串 { st[now^1].push(all++); } int top=st[now^1].top(); //找到s[i]可以接的子串編號 vv.push_back(top); //存入s[i]所屬子串編號 st[now^1].pop(); // 現在的第top子串,已經接上了s[i],那麼它的末尾就變了, 0->1/1->0,所以要把top傳過去 st[now].push(top); } all--; cout<<all<<endl; for(int i=0;i<vv.size();i++) cout<<vv[i]<<" "; cout<<endl; } }