2018百度之星资格赛

HDU6344 调查问卷

二进制状态压缩,判断相同对数sum,总对数               C\binom{n}{2}-sum>=k

#include<bits/stdc++.h>
using namespace std;
const int MAX=1025;
int a[MAX];//二进制串
int num[MAX];
int main()
{
    int t,n,m,K;
    char str[11];
    scanf("%d",&t);
    for(int tc=1;tc<=t;tc++)
    {
        memset(a,0,sizeof(a));
        scanf("%d%d%d",&n,&m,&K);
        for(int i=0;i<n;i++)
        {
            scanf("%s",str);
            for(int j=0;j<m;j++)
            if(str[j]=='B') a[i]+=1<<j;
        }
        if(n==1) {printf("Case #%d: 0\n",tc);continue;}
        int ans=0;
        for(int i=1;i<(1<<m);i++)
        {
            memset(num,0,sizeof(num));
            for(int j=0;j<n;j++)
            {
                int x=a[j]&i;
                num[x]++;
            }
            int K0=0;
            for(int j=0;j<(1<<m);j++)
                K0+=num[j]*(num[j]-1)/2;
            if(K0<=n*(n-1)/2-K) ans++;
        }
        printf("Case #%d: %d\n",tc,ans);
    }
    return 0;
}

HDU6345 子串查询

字典序满足 “abc”>"a";"b">"a";所有长度子串中单个字母字典序最小

线段树维护区间最小值的个数

#include<stdio.h>
#include<string.h>
#include<math.h>
const int MAX=1e5+5;
char str[MAX];
struct node
{
    char a;
    int b;
    node(){a='Z';b=0;}
    node(node& x){a=x.a;b=x.b;}
}c[MAX*4];
void build(int rt,int l,int r)
{
    if(l==r)
    {
        c[rt].a=str[l-1];
        c[rt].b=1;
        return ;
    }
    int mid=(l+r)>>1;
    build(rt*2,l,mid);
    build(rt*2+1,mid+1,r);
    if(c[rt*2].a==c[rt*2+1].a){c[rt]=c[rt*2];c[rt].b+=c[rt*2+1].b;}
    else if(c[rt*2].a<c[rt*2+1].a) c[rt]=c[rt*2];
    else c[rt]=c[rt*2+1];
}
node query(int rt,int l,int r,int L,int R)
{
    if(L<=l&&R>=r) return c[rt];
    int mid=(l+r)>>1;
    node x,y;
    if (L<=mid) x=query(rt*2,l,mid,L,R);
    if (R>mid) y=query(rt*2+1,mid+1,r,L,R);
    if(x.a==y.a) x.b+=y.b;
    else if(x.a>y.a) x=y;
    return x;
}
int main()
{
    int t,n,q,l,r;
    scanf("%d",&t);
    for(int tc=1;tc<=t;tc++)
    {
        printf("Case #%d:\n",tc);
        scanf("%d%d",&n,&q);
        scanf("%s",str);
        build(1,1,n);
        while(q--)
        {
            scanf("%d%d",&l,&r);
            printf("%d\n",query(1,1,n,l,r).b);
        }
    }
    return 0;
}

HDU6348 序列计数

动态规划状态转移方程:            dp[i][j]=\sum_{k=1}^{j-1}(a[k]<a[j])dp[i-1][k]

dp[ i ][ j ]表示序列长度为i取到第j个数时的种类数

用树状数组维护取到第j个数时的a[ j ]前缀和( a[ j ]的前缀和中必定不包含a[ k ],a[ k ]>a[ j ] ),同时满足 j > k且a[ j ] > a[ k ]的单调性

把求和过程的复杂度优化到O(logn)

滚动数组优化内存

#include<bits/stdc++.h>
using namespace std;
const int MAX=1e4+5;
const long long MOD=1e9+7;
int a[MAX],n;
long long dp[2][MAX];
long long c[MAX],ans[MAX];
void add(int x,int v)
{
    while(x<=n){c[x]=(c[x]+v)%MOD;x+=x&-x;}
}
long long get(int x)
{
    long long sum=0;
    while(x){sum=(sum+c[x])%MOD;x-=x&-x;}
    return sum;
}
int main()
{
    int t;
    scanf("%d",&t);
    for(int tc=1;tc<=t;tc++)
    {
        memset(dp,0,sizeof(dp));
        scanf("%d",&n);
        for(int i=1;i<=n;i++) {scanf("%d",&a[i]);}
        for(int i=1;i<=n;i++) dp[1][i]=1;ans[1]=n;
        for(int i=2;i<=n;i++)
        {
            ans[i]=0;
            if(ans[i-1]==0) continue;
            memset(c,0,sizeof(c));
            for(int j=1;j<=n;j++)
            {
                dp[i%2][j]=get(a[j]-1);
                add(a[j],dp[(i-1)%2][j]);
                ans[i]=(ans[i]+dp[i%2][j])%MOD;
            }
        }
        printf("Case #%d:",tc);
        for(int i=1;i<=n;i++) printf(" %I64d",ans[i]);
        putchar('\n');
    }
    return 0;
}

HDU6349 三原色图

Kruskal计算最小生成树权值,优先队列维护最小边权

#include<bits/stdc++.h>
using namespace std;
const int MAX=1e2+5;
const int INF=0x3f3f3f3f;
int f[MAX],tot1,tot2;
struct Edge
{
    int a,b,w;
    Edge(){}
    Edge(int a_,int b_,int v_)
    {
        a=a_;b=b_;w=v_;
    }
    Edge(const Edge &e)
    {
        a=e.a;b=e.b;w=e.w;
    }
}e1[MAX],e2[MAX];
int q1[MAX],q2[MAX],L1,R1,L2,R2;
void add1(Edge &e)
{
    e1[tot1++]=e;
}
void add2(Edge &e)
{
    e2[tot2++]=e;
}
int find(int x)
{
    if(f[x]==-1) return x;
    else return f[x]=find(f[x]);
}
bool cmp(Edge &ea,Edge &eb)
{
    return ea.w<eb.w;
}
int kurskal1(int n)
{
    memset(f,-1,sizeof(f));
    sort(e1,e1+tot1,cmp);
    int cnt=0,ans=0;
    for(int i=0;i<tot1;i++)
    {
        int u=e1[i].a;
        int v=e1[i].b;
        int w=e1[i].w;
        if(cnt==n-1)
        {
            q1[++R1]=w;
            continue;
        }
        int t1=find(u);
        int t2=find(v);
        if(t1!=t2)
        {
            ans+=w;
            f[t1]=t2;
            cnt++;
        }
        else q1[++R1]=w;
    }
    sort(q1,q1+R1+1);
    if(cnt<n-1) return INF;
    else return ans;
}
int kurskal2(int n)
{
    memset(f,-1,sizeof(f));
    sort(e2,e2+tot2,cmp);
    int cnt=0,ans=0;
    for(int i=0;i<tot2;i++)
    {
        int u=e2[i].a;
        int v=e2[i].b;
        int w=e2[i].w;
        if(cnt==n-1)
        {
            q2[++R2]=w;
            continue;
        }
        int t1=find(u);
        int t2=find(v);
        if(t1!=t2)
        {
            ans+=w;
            f[t1]=t2;
            cnt++;
        }
        else q2[++R2]=w;
    }
    sort(q2,q2+R2+1);
    if(cnt<n-1) return INF;
    else return ans;
}
int main()
{
    int t,n,m,x,y,v;
    char s[5];
    scanf("%d",&t);
    for(int tc=1;tc<=t;tc++)
    {
        tot1=tot2=0;
        L1=L2=0;
        R1=R2=-1;
        scanf("%d%d",&n,&m);
        for(int i=0;i<m;i++)
        {
            scanf("%d%d%d%s",&x,&y,&v,s);
            Edge e(x,y,v);
            if(s[0]=='G') {add1(e);add2(e);}
            else if(s[0]=='R') {add1(e);q2[++R2]=v;}
            else {add2(e);q1[++R1]=v;}
        }
        int a1=kurskal1(n),a2=kurskal2(n);
        printf("Case #%d:\n",tc);
        for(int i=1;i<n-1;i++) printf("-1\n");
        for(int i=n-1;i<=m;i++)
        {
            int ans=min(a1,a2);
            if(ans>=INF) printf("-1\n");
            else printf("%d\n",ans);
            int as1=INF,as2=INF;
            if(L1<=R1) as1=q1[L1++];
            if(L2<=R2) as2=q2[L2++];
            a1=a1+as1;
            a2=a2+as2;
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Nrtostp/article/details/81434339
今日推荐