2018百度之星资格赛

HDU6344 调查问卷

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

#include
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

HDU6345 子串查询

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

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

#include
#include
#include
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=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
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
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=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;
}

你可能感兴趣的:(比赛)