前言:

期末考试重修还更博客= - =)

A. Cards for Friends

直接按题意模拟,看可以分成多少个2的次幂.

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+500;
int w[N];
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n;
        int x,y;
        cin>>x>>y>>n;
        int res=1;
        while(x%2==0)
        {
            res*=2;
            x/=2;
        }
        while(y%2==0)
        {
            res*=2;
            y/=2;
        }
        if(res>=n)    puts("YES");
        else        puts("NO");

    }
    return 0;
}

B. Fair Division

方法1:直接模拟,因为糖果一定是2/1的,就两种情况,所以你先把2的分析完奇偶讨论下即可.

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n;
        int cnt[3];memset(cnt,0,sizeof cnt);
        scanf("%d",&n);int x;
        for(int i=1;i<=n;i++)    scanf("%d",&x),cnt[x]++;
        if(cnt[2]&1)
        {
            cnt[1]-=2;
            if(cnt[1]<0)    puts("NO");
            else if(cnt[1]&1)    puts("NO");
            else puts("YES");
        }
        else
        {
            if(cnt[1]&1)    puts("NO");
            else            puts("YES");    
        }        
    }
    return 0;
}

方法2:假如不止1,2两种糖果咋办,题目要你平分,所以假如一个数在%sum/2之前出现过,就必然会有种平分方案.

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+500;
ll w[N];
map<ll,bool>mp;
int main()
{
    int T;
    //T=1;
    scanf("%d",&T);
    while(T--)
    {
        mp.clear();
        int n;
        ll sum=0;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)    
        {
            scanf("%lld",&w[i]);
            sum+=w[i];    
        }int flag=0;
        if(sum%2!=0)
        {
            puts("NO");flag=1;
        }sum/=2;ll res=0;
        for(int i=1;i<=n;i++)
        {
            if(sum==0)    break;
            res+=w[i];
            res%=sum;
            if(mp[res]&&!flag)
            {
                puts("YES");
                flag=1;break;
            }mp[res]=true;
        }
        if(!flag)    puts("NO");

    }
    return 0;
}

C. Long Jumps

题目已知这个方程,直接写个for就好了.

#include <bits/stdc++.h>
using namespace std;
const int N=2e5+500;
typedef long long ll;
ll f[N];int a[N];
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)    scanf("%d",&a[i]),f[i]=a[i];
        ll ans=0;
        for(int i=1;i<=n;i++)
        {
            ans=max(f[i],ans);
            if(i+a[i]>n)    continue;
            f[i+a[i]]=max(f[i+a[i]],f[i]+a[i+a[i]]);
        }cout<<ans<<'\n';
    }
    return 0;
} 

D. Even-Odd Game

把奇偶分开,然后我们站在Alice和BOb的角度进行选择,假如你是Alice,Bob选下一个获得比你多,那么你肯定是不让Bob加分,Alice同理.

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+500;
int even[N],odd[N];
bool cmp(int A,int B)
{
    return A>B;
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        ll res_A=0,res_B=0;
        int idA=0,idB=0;
        int n;scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            int x;
            scanf("%d",&x);
            if(x&1)    odd[++idB]=x;
            else    even[++idA]=x;
        }
        sort(even+1,even+1+idA,cmp);
        sort(odd+1,odd+1+idB,cmp);
        int nA=1,nB=1;
        for(int i=1;i<=n;i++)
        {
            if(i&1)//Alice选择
            {
                if(nB<=idB&&nA<=idA)
                {
                    if(even[nA]>odd[nB])    res_A+=even[nA],nA++;
                    else                            nB++;
                }
                else if(nB<=idB)    nB++;
                else res_A+=even[nA],nA++;
            }
            else//Bob选择. 
            {
                if(nB<=idB&&nA<=idA)
                {
                    if(even[nA]<odd[nB])    res_B+=odd[nB],nB++;
                    else                    nA++;
                }
                else if(nA<=idA)    nA++;
                else res_B+=odd[nB],nB++;
            } 
        }
        if(res_A>res_B)            puts("Alice");
        else if(res_A==res_B)    puts("Tie");
        else                    puts("Bob");
    }    
    return 0;
}

E. Correct Placement

无法就是让你在二维平面找到两维都比自己小的数,另一种方案就是x,y交换一下放入数组,然后我们维护一维,另外一维维护一个min即可.

#include <bits/stdc++.h>
using namespace std;
const int N=2e5+500;
int ans[N<<1];
struct Tree{
    int l,r,idx;
}w[N<<1];
bool cmp(Tree A,Tree B)
{
    if(A.l==B.l)    return A.r<B.r;
    else            return A.l<B.l;    
}
int _val[N<<1],_id[N<<1];//维护到了i,r的最小值以及下标即可. 
int main()
{
    int T;scanf("%d",&T);
    while(T--)
    {
        int n;scanf("%d",&n);
        int id=n;
        for(int i=1;i<=n;i++)
        {
            ans[i]=0;
            scanf("%d%d",&w[i].l,&w[i].r);w[i].idx=i;
            w[++id].l=w[i].r;w[id].r=w[i].l,w[id].idx=i;
        }sort(w+1,w+1+id,cmp);
        int last=-1;//维护前一个r的最小值即可. 
        _val[0]=2e9,_id[0]=-1;
        for(int i=1;i<=id;i++)
        {
            _val[i]=_val[i-1],_id[i]=_id[i-1];
            if(w[i].r<_val[i])    _val[i]=w[i].r,_id[i]=w[i].idx;
            if(w[i].l>w[i-1].l)
            {
                last=i-1;
                if(w[i].r>_val[i])    ans[w[i].idx]=_id[i];
                else                ans[w[i].idx]=-1;
            }
            else//只能找last前面的数. 
            {
                if(w[i].r>_val[last])    ans[w[i].idx]=_id[last];
                else                    ans[w[i].idx]=-1;
            }
        }
        for(int i=1;i<=n;i++)    printf("%d ",ans[i]);
        puts("");
    }
}

F. New Year's Puzzle

简单模拟即可.模拟每个障碍下你是不是能填完,然后假如可以填完就是YES,否则就是NO.

#include <bits/stdc++.h>
using namespace std;
const int N=2e5+500;
struct Graph
{
    int r,c;
}w[N];

bool cmp(Graph A,Graph B)
{
    if(A.c==B.c)    return A.r<B.r;
    else            return A.c<B.c;
}

int main()
{
    int T;scanf("%d",&T);
    while(T--)
    {
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++)    scanf("%d%d",&w[i].r,&w[i].c);    
        int r1=0,r2=0;//设置我已经填到哪里了.
        bool flag=true;sort(w+1,w+1+m,cmp);
        w[++m].r=1,w[m].c=n+1;
        w[++m].r=2,w[m].c=n+1;
        for(int i=1;i<=m;i++)
        {
            //cout<<r1<<' '<<r2<<endl;
            if(w[i].c==w[i+1].c)//两个一起处理. 
            {
                //cout<<r1<<' '<<w[i].c<<endl;
                if((max(r2,r1)-min(r2,r1))&1)    flag=false;
                r1=r2=w[i].c;
                i++;
            }
            else//单个处理 
            {
                int p=w[i].r;//在第p行. 
                if(p==1)
                {
                    if((w[i].c-r1)%2!=1&&((max(r2,r1)-min(r2,r1))%2!=0))    flag=false;
                    if((w[i].c-r1)%2==1)    r1=w[i].c;
                    else if((w[i].c-r1)%2!=1&&((max(r2,r1)-min(r2,r1))%2==0))    r1=w[i].c,r2=w[i].c-1;
                }
                else
                {
                    if((w[i].c-r2)%2!=1&&((max(r2,r1)-min(r2,r1))%2!=0))    flag=false;
                    if((w[i].c-r2)%2==1)    
                    {
                        r2=w[i].c;
                    }
                    else if(((w[i].c-r2)%2!=1)&&((max(r2,r1)-min(r2,r1))%2==0))
                    {
                        r2=w[i].c,r1=w[i].c-1;
                    }    
                }
            }
        }//cout<<flag<<endl;
        if(flag)    puts("YES");
        else        puts("NO"); 
    }
    return 0;
}
/*
1
6 3
2 1
1 3
2 5 NO

1
5 2
2 2
2 3 YES
*/

G. Moving to the Capital

dp,先跑出题意要求的d[]数组,然后我们获得了一个bfs序,然后我们更新一次f[i],最后按bfs序更新一次即可.

#include <bits/stdc++.h>
using namespace std;
const int N=2e5+50;
int f[N],d[N];
vector<int>v[N];
vector<int>q;
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)    v[i].clear(),d[i]=-1;
        d[1]=0;q.clear();
        for(int i=1;i<=m;i++)
        {
            int x,y;scanf("%d%d",&x,&y);
            v[x].push_back(y);
        }q.push_back(1);
        for(int i=0;i<n;i++)
        {
            int u=q[i];
            for(int x:v[u])
            {
                if(d[x]==-1)
                {
                    d[x]=d[u]+1;
                    q.push_back(x);
                }
            }
        }//跑出所有d[i]. 
        for(int i=1;i<=n;i++)
        {
            f[i]=d[i];
            for(int x:v[i])
            {
                f[i]=min(f[i],d[x]);
            }
        }//预处理出来每个f[i]. 
        for(int i=n-1;i>=0;i--)
        {
            int u=q[i];
            for(int x:v[u])
            {
                if(d[u]<d[x])f[u]=min(f[u],f[x]);
            }
        }//按时间来dp. 
        for(int i=1;i<=n;i++)    printf("%d ",f[i]);
        puts("");
    }
    return 0;
}