4937: [Ceoi2016]popeala

来源:互联网 发布:mysql string length 编辑:程序博客网 时间:2024/06/18 14:40

垃圾T*B,推荐了这道题给我自己又弃了。。
然后我做了半天没有做出来
然后暴力DP大家都会
然后优化一下
然后有个地方口头AC很简单,然后打起来不是很会
脑子有点乱,暂时弃坑

#include<cstdio>#include<cstring>typedef long long LL;const int N=55;const int M=200005;const int MAX=1<<30;char ss[N][M];int n,m,S;int f[N][M];int a[N];int mymin (int x,int y){return x<y?x:y;}int mymax (int x,int y){return x>y?x:y;}void init (){    scanf("%d%d%d",&n,&m,&S);    for (int u=1;u<=m;u++) scanf("%d",&a[u]);    for (int u=1;u<=m;u++) a[u]=a[u]+a[u-1];    for (int u=1;u<=n;u++)   scanf("%s",ss[u]+1);}struct qq{    int l,r;    int s1,s2;    LL c;}s[M*2];int num=0;//这两位 void bt (int l,int r){    int a=++num;    s[a].l=l;s[a].r=r;    s[a].c=0;    if (l==r)    {        for (int i=1;i<=n;i++)            if (ss[i][l]=='1')                s[a].c=s[a].c+(1LL<<i-1);        return ;    }    int mid=l+r>>1;    s[a].s1=num+1;bt(l,mid);    s[a].s2=num+1;bt(mid+1,r);    s[a].c=s[s[a].s1].c&s[s[a].s2].c;}int find (int now,int l,int r){    if (s[now].l==l&&s[now].r==r)        return s[now].c;    int mid=(s[now].l+s[now].r)>>1;    int s1=s[now].s1,s2=s[now].s2;    if (r<=mid) return find(s[now].s1,l,r);    else if (l>mid) return find(s[now].s2,l,r);    else return find(s[now].s1,l,mid)&find(s[now].s2,mid+1,r);}int Get (int x){    int cnt=0;    while (x>0)    {        x=x&(x-1);        cnt++;    }    return cnt;}int get (int x,int y)//我们想得到从l~r的值 {    int xx=find(1,x,y);    return Get(xx)*(a[y]-a[x-1]);}void solve (){    num=0;    for (int u=1;u<=S;u++)//可以分成多少段     {        for (int i=1;i<=m;i++)//终点        {            for (int j=u;j<=i;j++)//起点在哪里                f[u][i]=mymin(f[u][i],f[u-1][j-1]+get(j,i));        }    }    for (int u=1;u<=S;u++) printf("%d\n",f[u][m]);}int main(){    init();    bt(1,m);    solve();    return 0;}
原创粉丝点击