长安大学校赛-2017

来源:互联网 发布:九天网络 编辑:程序博客网 时间:2024/04/28 01:19

比赛链接:长安大学校赛-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]>=xb[i] 放入到数据结构中,然后查询区间 [L,R] 内大于等于 y 的元素数量,可以用到分块+二分的数据结构离线动态查询(因为不会树套树)。
见:Codeforces-785E-Anton and Permutation(分块区间查询,动态查询[l,r]内小于某个值的元素个数)

#include<bits/stdc++.h>#define mp make_pair#define fi first#define se secondusing 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
原创粉丝点击