2022.5.29SCUACM暑假集训前欢乐赛

SCUACM暑假集训前欢乐赛 - Virtual Judge (vjudge.net)

A

先离散化

用树状数组去记录被包含的线段即可

还是很经典的题型了

#include<bits/stdc++.h>
using namespace std;
struct line{
    int l,r,id;
}w[200003];
int tot=0;
int a[400005],c[400005],ans[200003];
int n;
int lowbit(int x){return x&(-x);}
bool cmp(line a,line b)
{
    if(a.r==b.r)return a.l>b.l;
    return a.r<b.r;
}
void add(int x)
{
    while(x<=tot)
    {
        c[x]++;
        x+=lowbit(x);
    }
}
int query(int x)
{
    int res=0;
    while(x)
    {
        res+=c[x];
        x-=lowbit(x);
    }
    return res;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;++i)
    {
        w[i].id=i;
        scanf("%d%d",&w[i].l,&w[i].r);
        a[++tot]=w[i].l;
        a[++tot]=w[i].r;
    }
    sort(a+1,a+1+tot);
    sort(w+1,w+1+n,cmp);
    tot=unique(a+1,a+tot+1)-(a+1);
    for(int i=1;i<=n;++i)
    {
        int tx=lower_bound(a+1,a+1+tot,w[i].l)-a;
        int ty=lower_bound(a+1,a+1+tot,w[i].r)-a;
        //printf("???%d %d\n",query(tx-1),query(ty));
        ans[w[i].id]=query(ty)-query(tx-1);
        add(tx);
    }
    for(int i=1;i<=n;++i)printf("%d\n",ans[i]);
}
A

B

求方案数,考虑dp

dp[i]=dp[i-1]+dp[i-k]

#include<bits/stdc++.h>
#define LL long long
#define P 1000000007
using namespace std;
LL dp[100003],sum[100003];
int main()
{
    int T,k;scanf("%d%d",&T,&k);
    for(int i=0;i<k;++i)dp[i]=1;
    for(int i=k;i<=100002;++i)
    {
        dp[i]=dp[i-1]+dp[i-k];
        dp[i]%=P;
    }
    for(int i=1;i<=100002;++i)
    {
        sum[i]=sum[i-1]+dp[i];
        sum[i]%=P;
    }
    while(T--)
    {
        int a,b;scanf("%d%d",&a,&b);
        LL ans=sum[b]-sum[a-1];
        ans+=P;ans%=P;
        printf("%lld\n",ans);
    }
} 
B

C

C题当时做的时候题意理解错了卡了好久(脑袋抽抽)

先计算出w*a去判断能不能换,而不是看a是否为b的倍数

#include<bits/stdc++.h>
#define LL long long
using namespace std;
LL gcd(int x,int y)
{
    if (y==0)return x;
    return gcd(y,x%y);
}
int main()
{
    int n;
    double a,b;scanf("%d%lf%lf",&n,&a,&b);
    for(int i=1;i<=n;++i)
    {
        double x;scanf("%lf",&x);
        LL num=x*a/b;
        double num2=num*b/a;
        LL num3=num*(LL)b/(LL)a;
        if((double)num3<num2)num3++;
        printf("%lld ",(LL)x-num3);
    }
    
} 
C

D

判断bfs顺序是否合法,模拟判断

每次vector排序,有矛盾就输出No

#include<bits/stdc++.h>
#define LL long long
using namespace std;
vector<int>q,son;
vector<int>d[200005];
int a[200005],ord[200005];
int vis[200005];
int n;
bool cmp(int a,int b)
{
    return ord[a]<ord[b];
}
void bfs(int x)
{
    memset(vis,0,sizeof(vis));
    q.push_back(0);//下标问题 
    q.push_back(x);
    vis[x]=1;
    for(int i=1;i<=n;++i)
    {
        if(a[i]!=q[i])
        {
            printf("No\n");
            return;
        }
        int u=a[i];
        son.clear();
        for(int j=0;j<d[u].size();++j)
        {
            int v=d[u][j];
            if(vis[v])continue;
            son.push_back(v);
            vis[v]=1;
        }
        sort(son.begin(),son.end(),cmp);
        for(int j=0;j<son.size();++j)
          q.push_back(son[j]);
    }
    printf("Yes\n");
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<n;++i)
    {
        int a,b;scanf("%d%d",&a,&b);
        d[a].push_back(b);
        d[b].push_back(a);
    }
    for(int i=1;i<=n;++i)
    {
        scanf("%d",&a[i]);
        ord[a[i]]=i;
    }
    bfs(1);
} 
D

E

简单等比数列问题

#include<bits/stdc++.h>
#define LL long long
using namespace std;
int main()
{
    double a,b,c,d;scanf("%lf%lf%lf%lf",&a,&b,&c,&d);
    double p1=a/b,p2=c/d;
    double q=(1-p1)*(1-p2);
    double w=1;
    for(int i=1;i<=100000;++i)
      w*=q;
    printf("%.8lf",p1*(1-w)/(1-q));
} 
E

F

树上相邻的三个点颜色要不同,子树中儿子的颜色也不能相同

在dfs的时候判断

#include<bits/stdc++.h>
#define LL long long
using namespace std;
struct EDGE{
    int to,nextt;
}w[400003];
int n;
int tot=0;
int head[200003],color[200003];
void add(int a,int b)
{
    tot++;
    w[tot].nextt=head[a];
    w[tot].to=b;
    head[a]=tot;
}
void dfs(int x,int fa)
{
    int num=1;
    for(int i=head[x];i;i=w[i].nextt)
    {
        int v=w[i].to;
        if(v==fa)continue;
        while(num==color[x]||num==color[fa])num++;
        color[v]=num++;
        dfs(v,x);
    }
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<n;++i)
    {
        int x,y;scanf("%d%d",&x,&y);
        add(x,y);add(y,x);
    }
    color[1]=1;
    dfs(1,0);
    int ans=0;
    for(int i=1;i<=n;++i)ans=max(ans,color[i]);
    printf("%d\n",ans);
    for(int i=1;i<=n;++i)printf("%d ",color[i]);
} 
F

G

其实是思维题,发现可以转置的话其实就是对角线上的元素变动

对每条对角线上元素进行判断

#include<bits/stdc++.h>
#define LL long long
using namespace std;
int a[1003][1003],b[1003][1003];
int main()
{
    int n,m;scanf("%d%d",&n,&m);
    for(int i=1;i<=n;++i)
      for(int j=1;j<=m;++j)
        scanf("%d",&a[i][j]);
    for(int i=1;i<=n;++i)
      for(int j=1;j<=m;++j)
        scanf("%d",&b[i][j]);
    for(int i=1;i<=n;++i)
      for(int j=1;j<=m;++j)
        for(int k=1;k<=i+j+1;++k)
          if(a[k][i+j-k]==b[i][j])
          {
              a[k][i+j-k]=0;
              break;
          }
    int flagg=0;
    for(int i=1;i<=n;++i)
    {
        if(flagg)break;
        for(int j=1;j<=m;++j)
          if(a[i][j]!=0){flagg=1;break;}
    }
      
    if(flagg)printf("NO");
    else printf("YES");
} 
G

H

炮兵阵地,状压dp

枚举时考虑三排的状态

而且先把每种状态放的士兵预处理出来

#include <cstdio>
#include <cstring>
#define max(a,b) a>b?a:b
#define N 11
using namespace std;
int di[103],dp[103][1<<N][1<<N],soldier[103],state[1<<N];
bool check1(int a,int b)
{
    if(a&b) return true;
    return false;
}
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        char s[15];
        scanf("%s",s);
        for(int j=0;j<m;j++)
        {
            if(s[j]=='P') di[i]=di[i]<<1;
            else di[i]=(di[i]<<1)+1;
        }
    }
    int num=0;
    for(int i=0;i<(1<<m);i++)//最好是预处理出状态,而不是像牛吃草在dp过程中找状态,毕竟要统计不同状态的士兵数 
    {
        if(check1(i,i<<1)||check1(i,i<<2)) continue;
        int k=i;
        while(k)
        {
            soldier[num]+=k&1;
            k=k>>1;
        }
        state[num++]=i;
    }
     /***************************************/
   // for(int i=0; i<num; i++) printf("%d %d\n",state[i],soldier[i]);
    /***************************************/
    //dp[r][i][j]第r行为i状态,r-1行为j状态 
    for(int i=0;i<num;i++)
    {
        if(check1(state[i],di[1])) continue;
        dp[1][i][0]=soldier[i];
    }
    for(int i=0;i<num;i++)
    {
        if(check1(state[i],di[2])) continue;
        for(int j=0;j<num;j++)
        {
            if(check1(state[j],di[1])) continue;
            if(check1(state[i],state[j])) continue;
            dp[2][i][j]=max(dp[2][i][j],dp[1][j][0]+soldier[i]);
        }
    }
    for(int r=3;r<=n;r++)
    {
        for(int i=0;i<num;i++)
        {
            if(check1(state[i],di[r])) continue;
            for(int j=0;j<num;j++)
            {
                if(check1(state[j],di[r-1])) continue;
                if(check1(state[i],state[j])) continue;
                for(int k=0;k<num;k++)
                {
                    if(check1(state[k],di[r-2])) continue;
                    if(check1(state[k],state[i])||check1(state[j],state[k])) continue;
                    dp[r][i][j]=max(dp[r-1][j][k]+soldier[i],dp[r][i][j]);
                }
            }
        } 
    }
    int ans=0;
    for(int i=0;i<num;i++)
      for(int j=0;j<num;j++)
        ans=max(ans,dp[n][i][j]);
    printf("%d",ans);
} 
H
posted @ 2022-07-05 18:05  yyys  阅读(47)  评论(0编辑  收藏  举报