长安大学校赛-2017

4 篇文章 0 订阅
3 篇文章 0 订阅

比赛链接:长安大学校赛-2017

A:水

#include<bits/stdc++.h>
using namespace std;
int a[10]={1,0,0,0,0,0,1,0,2,1};
int main()
{
    int x,T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&x);
        if(x==0)
        {
            puts("1");
            continue;
        }
        int ans=0;
        while(x)
        {
            ans+=a[x%10];
            x/=10;
        }
        printf("%d\n",ans);
    }
    return 0;
}

B:贪心,每遇到一个字符,将其移动到合理的地方。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll INF=1e18+7;
char s[200007];
int main()
{
    int T,n;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        scanf("%s",s);
        n=n*2;
        ll ans=INF,res=0;
        int g=0,b=0;
        //GBGB
        for(int i=0;i<n;i++)
        {
            if(s[i]=='G'&&b>g) res+=b-g;
            else if(s[i]=='B'&&g>b) res+=g-b-1;
            if(s[i]=='G') g++;
            else b++;
        }
        ans=min(ans,res);
        //BGBG
        res=0;
        g=b=0;
        for(int i=0;i<n;i++)
        {
            if(s[i]=='G'&&b>g) res+=b-g-1;
            else if(s[i]=='B'&&g>b) res+=g-b;
            if(s[i]=='G') g++;
            else b++;
        }
        ans=min(ans,res);
        cout << ans << endl;
    }
    return 0;
}

D:我们将询问按照 x 排序,每得到一个询问将剩余的满足 a[i]>=x b[i] 放入到数据结构中,然后查询区间 [L,R] 内大于等于 y 的元素数量,可以用到分块+二分的数据结构离线动态查询(因为不会树套树)。
见:Codeforces-785E-Anton and Permutation(分块区间查询,动态查询[l,r]内小于某个值的元素个数)

#include<bits/stdc++.h>
#define mp make_pair
#define fi first
#define se second
using namespace std;
const int maxn=1e5+7;
int a[maxn],b[maxn],bl,sz,n,p[maxn],ans[maxn];
struct Block
{
    int l,r,len;
    vector<int> arr;
};
struct Query
{
    int l,r,x,y,id;
    bool operator < (const Query & r) const
    {
        return x>r.x;
    }
}Q[maxn];
Block block[350];
void init_block()
{
    for(int i=1;i<=sz;i++) block[i].len=0,block[i].arr.clear();
    for(int i=1;i<=n;i++)
    {
        int j=(i-1)/bl+1;
        if(!block[j].len) block[j].l=i;
        block[j].r=i;
        block[j].arr.push_back(0);
        block[j].len++;
    }
}
int query(int L,int R,int x,int y)
{
    int l=(L-1)/bl+1,r=(R-1)/bl+1;
    int res=0;
    if(l==r)
    {
        for(int i=L;i<=R;i++)
            res+=(a[i]>=x&&b[i]>=y);
    }
    else
    {
        for(int i=l+1;i<r;i++)
            res+=block[i].len-(lower_bound(block[i].arr.begin(),block[i].arr.end(),y)-block[i].arr.begin());
        for(int i=L;i<=block[l].r;i++)
            res+=(a[i]>=x&&b[i]>=y);
        for(int i=block[r].l;i<=R;i++)
            res+=(a[i]>=x&&b[i]>=y);
    }
    return res;
}
void update(int x)
{
    int X=(x-1)/bl+1;
    vector<int> &arr=block[X].arr;
    arr.erase(arr.begin());
    arr.insert(lower_bound(arr.begin(),arr.end(),b[x]),b[x]);
}
bool cmp(int a,int b)
{
    return ::a[a]>::a[b];
}
int main()
{
    int m,T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        for(int i=1;i<=n;i++) scanf("%d",&b[i]);
        for(int i=1;i<=n;i++) p[i]=i;
        sort(p+1,p+1+n,cmp);
        bl=sqrt(n);sz=(n-1)/bl+1;
        init_block();
        for(int i=0;i<m;i++)
        {
            scanf("%d%d%d%d",&Q[i].l,&Q[i].r,&Q[i].x,&Q[i].y);
            Q[i].id=i;
        }
        sort(Q,Q+m);
        int cur=1;
        for(int i=0;i<m;i++)
        {
            while(cur<=n&&a[p[cur]]>=Q[i].x) update(p[cur++]);
            ans[Q[i].id]=query(Q[i].l,Q[i].r,Q[i].x,Q[i].y);
        }
        for(int i=0;i<m;i++) printf("%d\n",ans[i]);

    }
    return 0;
}

E:设 dp[i] 为前 i 个的方案数,
dp[i]=[j,i]dp[j]

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
ll dp[100007];
char s[100007];
int a[100007];
bool vis[26];
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%s",s+1);
        int n=strlen(s+1);
        for(int i=1;i<=n;i++) a[i]=s[i]-'a';
        dp[0]=1;
        for(int i=1;i<=n;i++)
        {
            memset(vis,0,sizeof(vis));
            dp[i]=0;
            for(int j=i;j>=1;j--)
            {
                if(!vis[a[j]])
                {
                    vis[a[j]]=true;
                    dp[i]=(dp[i]+dp[j-1])%mod;
                }
                else break;
            }
        }
        cout << dp[n] << endl;
    }
    return 0;
}

G:同一个集合中的任意两点间没有边,表现在补图中就是完全图,不同集合间的任意两点间有边,表现在补图中就是不同的集合属于不同的联通集。所以我们处理出补图,进行上述的检测就行了。

#include<bits/stdc++.h>
using namespace std;
const int maxn=1007;
bool G[maxn][maxn],vis[maxn];
vector<int> adj[maxn],p;
void dfs(int u)
{
    vis[u]=true;
    p.push_back(u);
    for(int i=0;i<adj[u].size();i++)
    {
        int v=adj[u][i];
        if(vis[v]) continue;
        dfs(v);
    }
}
bool check()
{
    int n=p.size();
    for(int i=0;i<n;i++)
        for(int j=i+1;j<n;j++)
        {
            int u=p[i],v=p[j];
            if(G[u][v]) return false;
        }
    return true;
}
int main()
{
    int n,m;
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        memset(G,0,sizeof(G));
        memset(vis,0,sizeof(vis));
        int u,v;
        while(m--)
        {
            scanf("%d%d",&u,&v);
            G[u][v]=G[v][u]=true;
        }
        for(int i=1;i<=n;i++) adj[i].clear();
        for(int i=1;i<=n;i++)
            for(int j=i+1;j<=n;j++)
                if(!G[i][j])
                {
                    adj[i].push_back(j);
                    adj[j].push_back(i);
                }
        int k=0;
        bool flag=true;
        for(int i=1;i<=n;i++)
        {
            p.clear();
            if(!vis[i])
            {
                dfs(i);
                if(check()) ++k;
                else
                {
                    flag=false;
                    break;
                }
            }
        }
        if(flag&&k>=2) printf("%d\n",k);
        else puts("0");
    }
    return 0;
}

J:枚举每个字母就行。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int INF=1e9+7;
char s[100007];
int a[100007];
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n,m;
        scanf("%d%d",&n,&m);
        scanf("%s",s);
        int l=n*m;
        for(int i=0;i<l;i++) a[i]=s[i]-'a';
        ll ans=0;
        for(int i=0;i<n;i++)
        {
            int res=INF;
            for(int k=0;k<26;k++)
            {
                int t=0;
                for(int j=0;j<m;j++)
                    t+=abs(a[i+j*n]-k);
                res=min(t,res);
            }
            ans+=res;
        }
        cout << ans << endl;
    }
    return 0;
}

L:处理出所有符合条件的数,然后二分查询就行了。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
vector<ll> a;
int main()
{
    int T;
    scanf("%d",&T);
    for(int i=1;i<=6;i++)
    {
        for(int j=1;j<=9;j++)
        {
            for(int k=0;k<=9;k++)
            {
                ll t=0;
                for(int p=0;p<i;p++) t*=10,t+=j;
                for(int p=i;p<2*i;p++) t*=10,t+=k;
                for(int p=2*i;p<3*i;p++) t*=10,t+=j;
                a.push_back(t);
            }
        }
    }
    sort(a.begin(),a.end());
    while(T--)
    {
        ll l,r;
        cin>>l>>r;
        int ans=upper_bound(a.begin(),a.end(),r)-a.begin();
        ans-=lower_bound(a.begin(),a.end(),l)-a.begin();
        printf("%d\n",ans);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值