APIO2015泛做

可以在UOJ上提交可以在bzoj上提交(权限)

A. Bali Sculptures

对于前72%的数据,按位考虑,然后跑一点沙茶dp就行了。

dp:用f[x][y]表示前x位分为y段是否满足条件。

对于最后29%的数据,我们改一下dp方程。

dp:用f[x]表示前x位满足条件至少要分几段。

结论:傻逼题

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include <string.h>
#include <vector>
#include <math.h>
#include <limits>
#include <set>
#include <map>
using namespace std;
#define SZ 2066
typedef long long ll;
int n,a,b,yy[SZ];
#define S 50
ll inn=0,sum[SZ]; 
bool dp2[SZ][SZ];
bool chk2()
{
    for(int i=0;i<=n;i++)
        for(int j=0;j<=n;j++) dp2[i][j]=0;
    dp2[0][0]=1;
    for(int i=0;i<n;i++) //分i段 
    {
        for(int j=0;j<n;j++)
        {
            if(!dp2[i][j]) continue;
            for(int k=j+1;k<=n;k++)
            {
                if(((sum[k]-sum[j])|inn)==inn) dp2[i+1][k]=1;
            }
        }
    }
    for(int i=a;i<=b;i++) if(dp2[i][n]) return 1;
    return 0;
}
int dp1[SZ];
const int inf=1000000000;
bool chk1()
{
    dp1[0]=0;
    for(int i=1;i<=n;i++) dp1[i]=inf;
    for(int j=0;j<n;j++)
    {
        if(dp1[j]==inf) continue;
        for(int k=j+1;k<=n;k++)
        {
            if(((sum[k]-sum[j])|inn)==inn) dp1[k]=min(dp1[k],dp1[j]+1);
        }
    }
    return dp1[n]<=b;
}
int main()
{
    scanf("%d%d%d",&n,&a,&b);
    for(int i=1;i<=n;i++) scanf("%d",yy+i), sum[i]=sum[i-1]+yy[i];
    inn=(1LL<<S)-1;
    for(int i=S;i>=1;i--)
    {
        inn^=1LL<<(i-1);
        if(!((a==1)?chk1():chk2())) inn^=1LL<<(i-1);
    }
    printf("%lld\n",inn);
}

B. Jakarta Skyscrapers

据说可以卡时过?然而UOJ有hack啊根本过不了

等知道正解了再来补

C. Palembang Bridges

一座桥的时候,容易发现要建在中位数的地方。

两座桥的时候,按照每个人的家和办公室位置和排序后,一定存在一个分割点使得前缀都走左边的桥,后缀都走右边的桥,这似乎挺显然的。

然后离散完随手树状数组+二分维护一下中位数啥的即可。

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include <string.h>
#include <vector>
#include <math.h>
#include <limits>
#include <set>
#include <map>
using namespace std;
#define SZ 666666
typedef long long ll;
int K,n,as[SZ],bs[SZ],ap[SZ];
ll ans=0;
int Abs(int x) {return (x>=0)?x:-x;}
ll a_1()
{
    ll aa=0; int nn=0;
    for(int i=1;i<=n;i++) ap[++nn]=as[i];
    for(int i=1;i<=n;i++) ap[++nn]=bs[i];
    sort(ap+1,ap+1+nn);
    int md=ap[(nn+1)>>1];
    for(int i=1;i<=nn;i++) aa+=Abs(ap[i]-md);
    return aa;
}
typedef pair<int,int> pii;
pii zs[SZ];
bool cmp(pii a,pii b) {return a.first+a.second<b.first+b.second;}
#define SN 233333
struct Bits
{
ll bits[SZ];
ll sum(int x)
{
    ll ans=0;
    for(;x>=1;x-=x&-x) ans+=bits[x];
    return ans;
}
ll sum(int l,int r) {return sum(r)-sum(l-1);}
void edit(int x,ll y)
{
    for(;x<=SN;x+=x&-x) bits[x]+=y;
}
void clr() {for(int i=1;i<=SN;i++) bits[i]=0;}
}B1,B2;
ll zd[SZ],fd[SZ];
#define ls(x) (lower_bound(ap+1,ap+1+nn,x)-ap)
ll a_2()
{
    ll aa=20000000000000000LL; int nn=0;
    for(int i=1;i<=n;i++) ap[++nn]=as[i];
    for(int i=1;i<=n;i++) ap[++nn]=bs[i];
    sort(ap+1,ap+1+nn);
    nn=unique(ap+1,ap+1+nn)-ap-1;
    for(int i=1;i<=n;i++) zs[i].first=as[i], zs[i].second=bs[i];
    sort(zs+1,zs+1+n,cmp);
    B1.clr(); B2.clr();
    for(int i=1;i<=n;i++)
    {
        int A=ls(zs[i].first),B=ls(zs[i].second);
        B1.edit(A,1);
        B2.edit(A,zs[i].first);
        B1.edit(B,1);
        B2.edit(B,zs[i].second);
        int l=0,r=nn;
        while(l<r)
        {
            int mid=(l+r)>>1;
            int s=B1.sum(mid);
            if(s<i) l=mid+1; else r=mid;
        }
        int mn=ap[l];
        ll cans=B1.sum(l)*mn-B2.sum(l)+B2.sum(l,nn)-B1.sum(l,nn)*mn;
        zd[i]=cans;
    }
    B1.clr(); B2.clr();
    for(int i=n;i>=1;i--)
    {
        int A=ls(zs[i].first),B=ls(zs[i].second);
        B1.edit(A,1);
        B2.edit(A,zs[i].first);
        B1.edit(B,1);
        B2.edit(B,zs[i].second);
        int l=0,r=nn;
        while(l<r)
        {
            int mid=l+r>>1;
            int s=B1.sum(mid);
            if(s<n+1-i) l=mid+1; else r=mid;
        }
        int mn=ap[l];
        ll cans=B1.sum(l)*mn-B2.sum(l)+B2.sum(l,nn)-B1.sum(l,nn)*mn;
        fd[i]=cans;
    }
    for(int i=1;i<=n+1;i++) aa=min(aa,zd[i-1]+fd[i]);
    return aa;
}
int main()
{
    int N; scanf("%d%d",&K,&N);
    for(int i=1;i<=N;i++)
    {
        char a[3],c[3]; int b,d;
        scanf("%s%d%s%d",a,&b,c,&d);
        if(a[0]==c[0])
        {
            ans+=Abs(b-d);
            continue;
        }
        ++n; as[n]=b; bs[n]=d;
    }
    if(K==1) printf("%lld\n",a_1()+ans+n);
    else printf("%lld\n",a_2()+ans+n);
}
posted @ 2016-04-25 22:27  fjzzq2002  阅读(336)  评论(0编辑  收藏  举报