2018暑期集训选拔考试题解

 

前几天把上次考试的题补得差不多了。差最后一题,貌似加上离散化后把原题写炸了,始终没有A掉。等集训一段时间在回头看这题吧。

正好暑期集训即将开始,感觉已经在家咸鱼了一个星期,再不做题怕是要爆零了。。。

------------------------------------------------------------------------------------------------------------------------------------------------------------

8月5日更新:最后一题已经AC了~,又干了3个小时。。。

-------------------------------------------------------------------------------------------------------------------------------------------------------------

A题(智能停车场)(xdoj1334)

模拟,可以按车辆到达时间排个序,然后对于每辆车,直接照车位就可以了。

代码:

#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
typedef struct
{
    int s;
    int e;
    int ind;
    int w;
}  Car;
Car p[1010];
Car st[10100];
bool cmp1(Car x,Car y)
{
    if(x.s!=y.s)
    return x.s=st[j].e)
            {
                ind=j;
                break;
            }
        }
        p[i].w=ind;
        st[ind].e=p[i].e;
    }
    sort(p+1,p+n+1,cmp2);
    printf("%d",p[1].w);
    for(int i=2;i<=n;i++)
    printf(" %d",p[i].w);
    return 0;
}

B题(珂朵莉,威廉和第七兽)(xdoj1327)

直接暴搜,签到题。

代码:

#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
char maze[55][55];
int mp[55][55];
int vis[55][55];
int c1,c2,c3,c4=0;
int dx[4]={1,-1,0,0};
int dy[4]={0,0,-1,1};
int n,m;
void dfs(int x,int y,int num)
{
     for(int i=0;i<=4;i++)
     {
         int tx=x+dx[i];
         int ty=y+dy[i];
         if(tx>=1&&tx<=n&&ty>=1&&ty<=m&&mp[tx][ty]==num&&!vis[tx][ty])
         {
              vis[tx][ty]=1;
              dfs(tx,ty,num);       
         }
     }
}
int main()
{
    scanf("%d%d",&n,&m);
    getchar();
    for(int i=1;i<=n;i++)
    {
        scanf("%s",maze[i]);
        getchar();
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=0;j

C题(拿石头的游戏)(xdoj1328)

白书上模板题-硬币游戏

相信学过博弈论后大家对这道题有了刚深入的理解。。。

 代码:

#include
using namespace std;
int X,K,A[110];
bool win[10010];
void solve()
{
    win[0]=false;
    for(int j=1;j<=X;j++)
    {
        win[j]=false;
        for(int i=0;i

 D题(忙碌的周末)(xdoj1333)

CF上原题,这道题关键在于推出这个集合中最多有三个数,分类讨论即可

代码(写的有点丑):

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
ll a[200010];
ll pre[100];
map mp;
int main()
{
    int n;
    int f=0;
       pre[0]=1;
    for(int i=0;i<=33;i++)
    {
        pre[i+1]=2*pre[i];
    }
    while(scanf("%d",&n)!=EOF)
    {
    f=0;    
    ll c[3];
    mp.clear();
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&a[i]);
        mp[a[i]]++;
    }
        sort(a+1,a+1+n);
        int cnt;
        for(int i=1;i<=n;i++)
    {
        int u=0;
        c[u++]=a[i];
        cnt=0;
        for(int j=0;j<=34;j++)
        {
            if(mp[a[i]+pre[j]]!=0&&mp[a[i]+2*pre[j]]!=0)
            {
                c[1]=a[i]+pre[j];
                c[2]=a[i]+2*pre[j];
                cnt=2;
            }
              if(cnt==2)
            {
              printf("3\n");
              printf("%lld %lld %lld\n",c[0],c[1],c[2]);        
              f=1;
              break;
            }
        }
        if(f==1)
        {
            break;
        }
    }
    if(f==0)
    {
        for(int i=1;i<=n;i++)
      {
        int u=0;
        c[u++]=a[i];
        cnt=0;
        for(int j=0;j<=34;j++)
        {
            if(mp[a[i]+pre[j]]!=0)
            {
                c[u++]=a[i]+pre[j];
                cnt++;
            }
            if(cnt==1)
            {
              printf("2\n");
              printf("%lld %lld\n",c[0],c[1]);      
              f=1;
              break;
            }
        }
        if(f==1)
        break;
      }
    }
    if(f==0)
    {
        printf("1\n");
        printf("%lld\n",a[1]);
    }
  }
    return 0;
}

E题( 珂朵莉、威廉和第十一兽 )

这道题直接bfs即可,不过需要注意一些特殊情况,特判一下。

代码:

#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
typedef struct
{
	int x;
	int y;
	int c;
	int s;
} P;
int mp[110][110];
int vis[110][110];
int dx[4]={0,0,1,-1};
int dy[4]={1,-1,0,0};
char mmp[110][110];
int n,m,t,tx,ty,fx,fy;
int bfs()
{
	queue

q; P t1; t1.c=mp[fx][fy]; t1.s=0; t1.x=fx; t1.y=fy; q.push(t1); while(!q.empty()) { P tt=q.front(); q.pop(); if(tt.x==tx&&tt.y==ty) return tt.s; for(int i=0;i<4;i++) { int nx=tt.x+dx[i]; int ny=tt.y+dy[i]; int pan=(tt.c+1)%t; if(pan==0) pan=t; if(nx>=1&&nx<=n&&ny>=1&&ny<=m&&mp[nx][ny]==pan&&!vis[nx][ny]) { P t2; vis[nx][ny]=1; t2.x=nx; t2.y=ny; t2.c=mp[nx][ny]; t2.s=tt.s+1; q.push(t2); } } } return -1; } int main() { while(scanf("%d%d%d",&n,&m,&t)!=EOF) { memset(vis,0,sizeof(vis)); for(int i=1;i<=n;i++) { scanf("%s",mmp[i]); } for(int i=1;i<=n;i++) { for(int j=0;j

F题(生命仪式)(xdoj1326)

区间dp,可参考NOIP原题-能量项链,套路是一样的。不过为什么用之前软院新生赛的标程会T掉呢?(滑稽)

代码:

#include
using namespace std;
typedef long long ll;
ll dp[810][810];
ll a[810];
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        memset(dp,0,sizeof(dp));
        memset(a,0,sizeof(a));
        for(int i=1;i<=n;i++)
        {
           scanf("%lld",&a[i]);
           a[n+i]=a[i];
        }
        for(int j=2;j<=2*n;j++)
        {
            for(int i=j-1;i>0&&j-i

G题(上海上海上海上海蓬莱蓬莱蓬莱蓬莱 ) (xdoj1329)

听之前想了很长时间也不会,听后秒懂系列。

把B当成-1,把R当成1,维护前缀和,再O(n)扫描一遍即可。

代码:

#include
using namespace std;
char s[1100000];
int a[1100000];
int sum[1100000];
int rec[1100000];
int flag[1100000];
int main()
{
    while(scanf("%s",s)!=EOF)
    {
        int len=strlen(s);
        memset(rec,0,sizeof(rec));
        memset(flag,0,sizeof(flag));
        for(int i=0;i

H题(天才琪露诺的完美算数教室 ) (xdoj1330)

打表异或前缀和找规律,这里直接用的题解的思路了,又特判一下0,1,2。不过这道题感觉还没有完全弄懂的样子。。。

代码:

#include
using namespace std;
typedef long long ll;
int main()
{
    ll t,n;
    scanf("%lld",&t);
    while(t--)
    {
        scanf("%lld",&n);
        if(n==0)
        {
            printf("4 7\n");
        }
        else if(n==1)
        {
            printf("1 5\n");
        }
        else if(n==2)
        {
            printf("3 5\n");
        }
        else
        {
           if(n%4==0)
          {
             printf("%d %lld\n",1,n);
          }
          else if(n%4==1)
          {
              printf("%d %lld\n",2,n-1);
          }
          else if(n%4==2)
          {
            printf("%d %lld\n",2,n);
          }
          else
          {
            printf("%d %lld\n",1,n-1);
          }
        }
    }
    return 0;
 } 

I题(区间第K大)(xdoj1336)

最开始想写二分+BIT,T掉了,而且也有些复杂。后来发现这道题满足区间递增性,用二分加尺取,直接过了。

大致思路就是每次二分时看比这个区间严格大的有多少个,如果这个数比K小就更新答案,不断逼近答案,最后得出解。

代码:

#include
using namespace std;  
typedef long long ll;
ll tem[100005];
ll sum[100005]; 
int n,k;
ll cal(ll mid)
{
    int r=1;
    ll res=0;
    for(int i=0;i>1;
            if (cal(mid)>=k) 
            l=mid+1;
            else
            {
                r=mid-1;
                ans=mid;
            }
        } 
        printf("%lld\n",ans); 
    return 0;   
}

------------------------------------------------------------------------------------------------------------------------------------------------------------ 

J题  火聚聚铺地毯(xdoj1324)

这道题可以说是poj3171和poj2528的一个结合版,难度加大了不少,在上次比赛中出现在最后一题的位置(不过有几位聚聚做出来了,膜)。首先总体上dp的思路是好想的,可以设dp[i]为到 i 位置的最小花费,易得dp[i]=min(dp[j])+c[i].w;(a[i].l-1<=j<=a[i].r)。可是这么算复杂度是O(n^2),要超时的。因为是区间查询最值问题,想到线段树。用Minv数组维护dp数组,每次查询之前区间的最小值为log(sum),sum为地毯总长度,不过这道题sum过大,线段树存不下,考虑离散化。这道题还需要考虑相邻两个点之间离散化后若相邻,需判断原来两个点是否直接相邻,若不,再中间加一个点(详见代码)。此时sum最高为400000左右,总复杂度nlog(sum), 刚刚好。

代码:

#include 
#include 
#include 
using namespace std;
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
typedef long long ll;
const int maxn = 400010;
int Min[maxn<<2];
void PushUP(int rt) {
       Min[rt] = min(Min[rt<<1] , Min[rt<<1|1]);
}
typedef struct
{
	ll li;
	ll ri;
	int w;
} Cloth;
Cloth c[100010];
Cloth ccopy[100010];
ll lisan[400040];
bool cmp(Cloth x,Cloth y)
{
	if(x.li!=y.li)
	return x.li> 1;
       build(lson);
       build(rson);
}
void update(int p,int sc,int l,int r,int rt) {
       if (l == r) {
              Min[rt] = min(Min[rt],sc);
              return ;
       }
       int m = (l + r) >> 1;
       if (p <= m) update(p , sc , lson);
       else update(p , sc , rson);
       PushUP(rt);
}
int query(int L,int R,int l,int r,int rt) {
       if (L <= l && r <= R) {
              return Min[rt];
       }
       int m = (l + r) >> 1;
       int ret = 2e9;
       if (L <= m) ret = min(ret , query(L , R , lson));
       if (R > m) ret = min(ret , query(L , R , rson));
       return ret;
}
int main() 
{
       int n;
       ll m,e;
       scanf("%d%lld%lld",&n,&m,&e);
       for(int i=0;i1)
	   	   {
	   	      	lisan[num++]=lisan[i-1]+1;
		   }
	   }
	   sort(lisan,lisan+num);
	   ll mm = lower_bound(lisan,lisan+num,m)-lisan;
	   mm++;
	   ll ee = lower_bound(lisan,lisan+num,e)-lisan;
	   ee++;
	   for(int i=0;icur+1)
           {
           	   flag=0;
           	   break;
		   }
		   int tem=query(c[i].li-1,c[i].ri,mm-1,ee,1);
		   update(c[i].ri,tem+c[i].w,mm-1,ee,1);
		   cur=max(cur,ccopy[i].ri);
	   }
	   if(e > cur)
	   {
	      printf("-1\n");
          return 0;
       }
	   if(flag)
	   printf("%d\n",query(ee,ee,mm-1,ee,1));
	   else
	   printf("-1\n");
       return 0;
}

 

 

 

你可能感兴趣的:(赛后总结)