1. 程式人生 > 實用技巧 >Codeforces Round #661 (Div. 3)(A->D)

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;
    }
}