2015ACM/ICPC亚洲区长春站部分题解

所有题目链接:http://acm.hdu.edu.cn/search.php?field=problem&key=2015ACM%2FICPC%D1%C7%D6%DE%C7%F8%B3%A4%B4%BA%D5%BE-%D6%D8%CF%D6%C8%FC%A3%A8%B8%D0%D0%BB%B6%AB%B1%B1%CA%A6%B4%F3%A3%A9&source=1&searchmode=source

F。Almost Sorted Array

判断一个数组中的数是不是几乎排好序的,几乎排好序的意思就是去掉一个后能成为排好序的数组,只要求下最长单增或单减子序列就好,
如果长度等于数组的长度或者等于数组长度-1就是一个符合的序列。

#include <cstdio>
#include <cstdio>
#include <cstring>
#include <cctype>
#include <cmath>
#include <set>
#include <map>
#include <list>
#include <queue>
#include <deque>
#include <stack>
#include <string>
#include <bitset>
#include <vector>
#include <iostream>
#include <algorithm>
#define max(a,b) ((a)>(b)?(a):(b))
#define mem(a,b) memset(a,b,sizeof(a))
#define For(a,l,r) for(int a=l;a<r;a++)
#define F first
#define S second
using namespace std;

typedef  long long LL;
const LL  mod = 9973;
const LL  inf=0x3f3f3f3f;
const double pi=acos(-1);
const int N=200005;//最大点数
const int M=13;// 最大边数

int T,n,m;
int a[100005];
int dp[100005];

int main()
{
#ifdef LOCALHEI
    freopen("date.in","r",stdin);
    freopen("date.out","w",stdout);
#endif
    scanf("%d",&T);
    while(T--)
    //while(scanf("%d%d",&n,&m)!=EOF)
    {
        scanf("%d",&n);
        int len=0;
        scanf("%d",&a[0]);
        dp[++len]=a[0];
        for(int i=1;i<n;i++)
        {
            scanf("%d",&a[i]);
            if(dp[len]<=a[i])dp[++len]=a[i];
                else
                {
                    int l=1,r=len;
                    while(l<=r)
                    {
                int mid=(l+r)/2;
                if(dp[mid]>a[i])r=mid-1;
                else l=mid+1;
                    }
                    dp[l]=a[i];
                } 


        }
        //cout<<len<<endl;
        if(len>=n-1)
        {
            puts("YES");
            continue;
        }
        len=0;
        dp[++len]=a[0];
        for(int i=1;i<n;i++)
        {
            if(dp[len]>=a[i])dp[++len]=a[i];
                else
                {
                    int l=1,r=len;
                    while(l<=r)
                    {
                int mid=(l+r)/2;
                if(dp[mid]<a[i])r=mid-1;
                else l=mid+1;
                    }
                    dp[l]=a[i];
                } 


        }
        //cout<<len<<endl;
        if(len>=n-1)
        {
            puts("YES");
            continue;
        }
        puts("NO");
    }
    return 0;
}

G。Dancing Stars on Me

给出一些点,判断能否在全用上这些点的情况下构成一个正多边形且边长为整数,易知只能构成正四边形。排序选好各对应边,判断长度是否相等就好。

#include <cstdio>
#include <cstdio>
#include <cstring>
#include <cctype>
#include <cmath>
#include <set>
#include <map>
#include <list>
#include <queue>
#include <deque>
#include <stack>
#include <string>
#include <bitset>
#include <vector>
#include <iostream>
#include <algorithm>
#define max(a,b) ((a)>(b)?(a):(b))
#define mem(a,b) memset(a,b,sizeof(a))
#define For(a,l,r) for(int a=l;a<r;a++)
#define F first
#define S second
using namespace std;

typedef  long long LL;
const LL  mod = 9973;
const LL  inf=0x3f3f3f3f;
const double pi=acos(-1);
const int N=200005;//最大点数
const int M=13;// 最大边数
struct node
{
    int x,y;
}p[106];
bool cmp(node a,node b)
{
    if(a.x==b.x)
        return a.y<b.y;
    else return a.x<b.x;
}
int T,n,m;
bool check()
{
    sort(p,p+4,cmp);
    long long s[5];
    s[0]=(p[0].x-p[1].x)*(p[0].x-p[1].x)+(p[0].y-p[1].y)*(p[0].y-p[1].y);
    s[1]=(p[0].x-p[2].x)*(p[0].x-p[2].x)+(p[0].y-p[2].y)*(p[0].y-p[2].y);
    s[2]=(p[3].x-p[1].x)*(p[3].x-p[1].x)+(p[3].y-p[1].y)*(p[3].y-p[1].y);
    s[3]=(p[2].x-p[3].x)*(p[2].x-p[3].x)+(p[2].y-p[3].y)*(p[2].y-p[3].y);
    sort(s,s+4);
if(s[0]==s[3])
    return true;
else 
    return false ; 
}
int main()
{
#ifdef LOCALHEI
    freopen("date.in","r",stdin);
    freopen("date.out","w",stdout);
#endif
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        for(int i=0;i<n;i++)
            scanf("%d%d",&p[i].x,&p[i].y);
        if(n!=4)
        {
            puts("NO");
            continue;
        }
        if(check())
        {
            puts("YES");
        }
        else puts("NO");
    }
    return 0;
}

H - Partial Tree
n个点生成一棵树,每个节点度数不同,权值也不同,求出最大权值的树。每个节点至少要有一个度,总共有2*n-2个度,把剩下的n-2个度分到n个节点中。问题转化成将重量分别为1->n-2,价值分别为v[i](2<=i<=n-1)的物品放到体积为n-2的背包中,v[i]=f[i]-f[1],即通过改变一些度为1的节点使其达到度为i。可以用完全背包求解,需要注意的是要通过放入体积为x的 物品使其体积达到y,那么之前放到的物品一定是要能达到y-x的。

#include <cstdio>
#include <cstdio>
#include <cstring>
#include <cctype>
#include <cmath>
#include <set>
#include <map>
#include <list>
#include <queue>
#include <deque>
#include <stack>
#include <string>
#include <bitset>
#include <vector>
#include <iostream>
#include <algorithm>
#define max(a,b) ((a)>(b)?(a):(b))
#define mem(a,b) memset(a,b,sizeof(a))
#define For(a,l,r) for(int a=l;a<r;a++)
#define F first
#define S second
using namespace std;

typedef  long long LL;
const LL  mod = 9973;
const LL  inf=0x3f3f3f3f;
const double pi=acos(-1);
const int N=200005;//最大点数
const int M=13;// 最大边数

int T,n,m;
int f[2016];
int dp[2016];
int main()
{
#ifdef LOCALHEI
    freopen("date.in","r",stdin);
    freopen("date.out","w",stdout);
#endif
    scanf("%d",&T);
    while(T--)
    {   
        scanf("%d",&n);
        for(int i=1;i<n;i++)
            scanf("%d",&f[i]);
        for(int i=0;i<=n;i++)
            dp[i]=-inf;
        dp[0]=0;
        for(int i=2;i<=n-1;i++) 
            for(int j=(i-1);j<=n-2;j++)
                if(dp[j-(i-1)]!=-inf)
                dp[j]=max(dp[j-(i-1)]+f[i]-f[1],dp[j]);
        printf("%d\n",f[1]*n+dp[n-2]);
    }
    return 0;
}

J - Chip Factory

给一些数,在这些数中选择三个互不相同的数,a、b、c,求最大的(a+b)XORc。
暴力会超时,可以用字典树优化,先把这些数存进字典树,然后两两求和判断,需要注意的是abc是不同的,所以a+b在字典树中寻值时应判断一下。两种方法:一种直接开bool数组判断,一种寻值前把a,b从树中删除。两种都贴一下。

#include <cstdio>
#include <cstdio>
#include <cstring>
#include <cctype>
#include <cmath>
#include <set>
#include <map>
#include <list>
#include <queue>
#include <deque>
#include <stack>
#include <string>
#include <bitset>
#include <vector>
#include <iostream>
#include <algorithm>
#define max(a,b) ((a)>(b)?(a):(b))
#define mem(a,b) memset(a,b,sizeof(a))
#define For(a,l,r) for(int a=l;a<r;a++)
#define F first
#define S second
using namespace std;

typedef  long long LL;
const LL  mod = 9973;
const LL  inf=0x3f3f3f3f;
const double pi=acos(-1);
const int N=200005;//最大点数
const int M=13;// 最大边数

int T,n,m;
int a[1005];
struct node
{
   bool fla[1000];
    struct node *nextt[2];
    int num;
};
struct node *root;
struct node *newset()
{
    struct  node *p;
    p=new(node);
    for(int i=0;i<2;i++)
    {
        p->nextt[i]=NULL;
    }
    p->num=0;
    memset(p->fla,false,sizeof(p->fla));
    return p;
}
void insert(int an,int pla)
{
    struct  node *p;
    p=root;
    p->num++;
    for(int i=30;i>=0;i--)
    {
        int tep=0;
        if((an&(1<<i))!=0)
        tep=1;
        if(p->nextt[tep]==NULL)
        {
            p->nextt[tep]=newset();
        }
        p=p->nextt[tep];
        p->fla[pla]=1;
        p->num++;
    }
}
int que(int an,int x,int y)
{
    node *p;
    p=root;
    int res=an;
    for(int i=30;i>=0;i--)
    {
        //printf("%d===\n",p->num);
        int tep=0;
        if((an&(1<<i))!=0)
        tep=1;
        if((p->nextt[tep^1]!=NULL)&&(((p->nextt[tep^1]->fla[x])&&(p->nextt[tep^1]->fla[y])&&(p->nextt[tep^1]->num>2))||((p->nextt[tep^1]->fla[x]==0)&&(p->nextt[tep^1]->fla[y])&&(p->nextt[tep^1]->num>1))||((p->nextt[tep^1]->fla[x])&&(p->nextt[tep^1]->fla[y]==0)&&(p->nextt[tep^1]->num>1))||((p->nextt[tep^1]->fla[x]==0)&&(p->nextt[tep^1]->fla[y]==0)&&(p->nextt[tep^1]->num>0))))
         {
            res|=(1<<i);
            p=p->nextt[tep^1];
         }
         else if(p->nextt[tep]!=NULL)
         {
            res&=(~(1<<i));
             p=p->nextt[tep];
            // printf("i= %d %d==\n",i,res);
         }
    }
    return res;
}
void clearr(node * root)//清空
{
    for(int i=0;i<2;i++)
    {
        if(root->nextt[i]!=NULL)
        {
            clearr(root->nextt[i]);
        }
    }
    free(root);
}
int main()
{
#ifdef LOCALHEI
    freopen("date.in","r",stdin);
    freopen("date.out","w",stdout);
#endif
    scanf("%d",&T);
    while(T--)
    {

        root=newset();
        scanf("%d",&n);
        for(int i=0;i<n;i++)
        {
            scanf("%d",&a[i]);
            insert(a[i],i);
        }
    // printf("%d=====\n",root->num);
        int ans=0;
        for(int i=0;i<n;i++)
            for(int j=i+1;j<n;j++)
            {
                //printf("%d %d 9999\n",a[i],a[j]);
                int aaa=que(a[i]+a[j],i,j);
                //cout<<que(a[i]+a[j],i,j)<<endl;
                ans=max(ans,aaa);
            }

            printf("%d\n",ans);
        clearr(root);
    }
    return 0;
}
#include <cstdio>
#include <cstdio>
#include <cstring>
#include <cctype>
#include <cmath>
#include <set>
#include <map>
#include <list>
#include <queue>
#include <deque>
#include <stack>
#include <string>
#include <bitset>
#include <vector>
#include <iostream>
#include <algorithm>
#define max(a,b) ((a)>(b)?(a):(b))
#define mem(a,b) memset(a,b,sizeof(a))
#define For(a,l,r) for(int a=l;a<r;a++)
#define F first
#define S second
using namespace std;

typedef  long long LL;
const LL  mod = 9973;
const LL  inf=0x3f3f3f3f;
const double pi=acos(-1);
const int N=200005;//最大点数
const int M=13;// 最大边数

int T,n,m;
int a[1005];
struct node
{
    struct node *nextt[2];
    int num;
};
struct node *root;
struct node *newset()
{
    struct  node *p;
    p=new(node);
    for(int i=0;i<2;i++)
    {
        p->nextt[i]=NULL;
    }
    p->num=0;
    return p;
}
void insert(int an)
{
    struct  node *p;
    p=root;
    p->num++;
    for(int i=30;i>=0;i--)
    {
        int tep=0;
        if((an&(1<<i))!=0)
        tep=1;
        if(p->nextt[tep]==NULL)
        {
            p->nextt[tep]=newset();
        }
        p=p->nextt[tep];
        p->num++;
    }
}
void del(int an)
{
    struct  node *p;
    p=root;
    p->num--;
    for(int i=30;i>=0;i--)
    {
        int tep=0;
        if((an&(1<<i))!=0)
        tep=1;
        p=p->nextt[tep];
        p->num--;
    }
}
int que(int an)
{
    node *p;
    p=root;
    int res=an;
    for(int i=30;i>=0;i--)
    {
        int tep=0;
        if((an&(1<<i))!=0)
        tep=1;
         if(p->nextt[tep^1]!=NULL&&p->nextt[tep^1]->num>0)
         {
            res|=(1<<i);
            p=p->nextt[tep^1];
         }
         else if(p->nextt[tep]!=NULL)
         {
            res&=(~(1<<i));
             p=p->nextt[tep];
         }
    }
    return res;
}
void clearr(node * root)//清空
{
    for(int i=0;i<2;i++)
    {
        if(root->nextt[i]!=NULL)
        {
            clearr(root->nextt[i]);
        }
    }
    free(root);
}
int main()
{
#ifdef LOCALHEI
    freopen("date.in","r",stdin);
    freopen("date.out","w",stdout);
#endif
    scanf("%d",&T);
    while(T--)
    {
        root=newset();
        scanf("%d",&n);
        for(int i=0;i<n;i++)
        {
            scanf("%d",&a[i]);
            insert(a[i]);
        }
        int ans=0;
        for(int i=0;i<n;i++)
            for(int j=i+1;j<n;j++)
            {
                del(a[i]);
                del(a[j]);
                int aaa=que(a[i]+a[j]);
                insert(a[i]);
                insert(a[j]);
                ans=max(ans,aaa);
            }

            printf("%d\n",ans);
        clearr(root);
    }
    return 0;
}

L - House Building
求物体表面积。
定面积加与四周高度的差就是一个凸起的表面积,遍历一下即可。

#include <cstdio>
#include <cstdio>
#include <cstring>
#include <cctype>
#include <cmath>
#include <set>
#include <map>
#include <list>
#include <queue>
#include <deque>
#include <stack>
#include <string>
#include <bitset>
#include <vector>
#include <iostream>
#include <algorithm>
#define max(a,b) ((a)>(b)?(a):(b))
#define mem(a,b) memset(a,b,sizeof(a))
#define For(a,l,r) for(int a=l;a<r;a++)
#define F first
#define S second
using namespace std;

typedef  long long LL;
const LL  mod = 9973;
const LL  inf=0x3f3f3f3f;
const double pi=acos(-1);
const int N=200005;//最大点数
const int M=13;// 最大边数

int T,n,m;
int a[55][55];

int main()
{
#ifdef LOCALHEI
    freopen("date.in","r",stdin);
    freopen("date.out","w",stdout);
#endif
    scanf("%d",&T);
    while(T--)
    //while(scanf("%d%d",&n,&m)!=EOF)
    {
        memset(a,0,sizeof(a));
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
            for (int j=1;j<=m;j++)
                scanf("%d",&a[i][j]);
            long long ans=0;
            for(int i=1;i<=n;i++)
                for(int j=1;j<=m;j++)
                {
                    if(a[i][j]==0)
                        continue;
                    ans+=1;
                    if(a[i][j]>a[i-1][j])
                        ans+=(a[i][j]-a[i-1][j]);
                    if(a[i][j]>a[i][j-1])
                        ans+=(a[i][j]-a[i][j-1]);
                    if(a[i][j]>a[i+1][j])
                        ans+=(a[i][j]-a[i+1][j]);
                    if(a[i][j]>a[i][j+1])
                        ans+=(a[i][j]-a[i][j+1]);
                }
                printf("%lld\n",ans);
    }
    return 0;
}

其它的等我足够强大再说==orz

你可能感兴趣的:(ACM,长春站,亚洲区域赛,Partial-Tr)