zoukankan      html  css  js  c++  java
  • APIO2015

    还没有写完APIO2015的题目,打算今天写一写。

    T1:

    按位DP,DP时要保证已确定的位为0。

    前4组设f[n][k]表示把前n个分成k组是否合法。

    最后一组设g[n]表示把前n个最少分为多少组才符合题意。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cctype>
    #define rep(i,s,t) for(int i=s;i<=t;i++)
    #define ren for(int i=first[x];i!=-1;i=next[i])
    using namespace std;
    inline int read() {
        int x=0,f=1;char c=getchar();
        for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
        for(;isdigit(c);c=getchar()) x=x*10+c-'0';
        return x*f;
    }
    const int maxn=2010;
    typedef long long ll;
    int n,A,B,f[110][110],g[maxn];
    ll t,S[maxn];
    int check(int x) {
        if(A==1) {
            g[0]=0;
            rep(i,1,n) {
                g[i]=1<<30;
                rep(j,0,i-1) if(!((S[i]-S[j])&t)) g[i]=min(g[i],g[j]+1);
            }
            return g[n]<=B;
        }
        memset(f,0,sizeof(f));
        f[0][0]=1;
        rep(i,1,n) rep(k,1,B) rep(j,0,i-1) if(!((S[i]-S[j])&t)&&f[j][k-1]) f[i][k]=1; 
        rep(i,A,B) if(f[n][i]) return 1;
        return 0;
    }
    int main() {
        n=read();A=read();B=read();
        rep(i,1,n) S[i]=S[i-1]+read();
        ll ans=0;
        for(int i=50;i>=0;i--) {
            t^=(1ll<<i);
            if(!check(i)) ans^=(1ll<<i),t^=(1ll<<i);
        }
        printf("%lld
    ",ans);
        return 0;
    }
    View Code

    T3:

    k=1时排序求中位数。

    k=2时设垮桥的所有两点坐标分别为x1i,x2i。设桥修在了p1,p2的位置,对于每对点(x1,x2),当(x1+x2)/2接近p1时肯定走p1,(x1+x2)/2接近p2时肯定走p2。故将所有点对按x1+x2升序排序,这样肯定存在一条分割线,使得分割线左侧的走左边一座桥,分割线右侧的走右边一座桥。这样我们实现一个可以支持插入和查询中位数的数据结构即可。Treap什么的就行了,但我DB地用了动态开节点的线段树。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cctype>
    #define rep(s,t) for(int i=s;i<=t;i++)
    #define ren for(int i=first[x];i!=-1;i=next[i])
    using namespace std;
    inline int read() {
        int x=0,f=1;char c=getchar();
        for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
        for(;isdigit(c);c=getchar()) x=x*10+c-'0';
        return x*f;
    }
    inline char getc() {
        char c=getchar();
        while(!isalpha(c)) c=getchar();
        return c;
    }
    const int maxn=200010;
    typedef long long ll;
    struct Point {
        int x1,x2;
        bool operator < (const Point& ths) const {return x1+x2<ths.x1+ths.x2;}
    }A[maxn];
    int k,n,tmp[maxn];
    ll ans,mn=(1ll<<60),f[maxn],g[maxn],sumv[10000010];
    int ls[10000010],rs[10000010],s[10000010],ToT,root;
    void insert(int& o,int l,int r,int pos) {
        if(!o) o=++ToT,s[o]=ls[o]=rs[o]=sumv[o]=0;
        s[o]++;sumv[o]+=pos;if(l==r) return;
        int mid=l+r>>1;
        if(pos<=mid) insert(ls[o],l,mid,pos);
        else insert(rs[o],mid+1,r,pos);
    }
    int kth(int o,int l,int r,int k) {
        if(l==r) return l;
        int k2=s[ls[o]],mid=l+r>>1;
        if(k2>=k) return kth(ls[o],l,mid,k);
        return kth(rs[o],mid+1,r,k-k2);
    }
    ll tot,sum;
    void query(int o,int l,int r,int ql,int qr) {
        if(!o) return;
        if(ql<=l&&r<=qr) {
            tot+=s[o];sum+=sumv[o];
            return;
        }
        int mid=l+r>>1;
        if(ql<=mid) query(ls[o],l,mid,ql,qr);
        if(qr>mid) query(rs[o],mid+1,r,ql,qr);
    }
    ll query(int o) {
        if(!o) return 0;
        int v=kth(o,0,1000000000,s[o]/2);
        ll ret=0;
        tot=sum=0;query(o,0,1000000000,0,v);ret+=tot*v-sum;
        tot=sum=0;query(o,0,1000000000,v,1000000000);ret-=tot*v-sum;
        return ret;
    }
    int main() {
        k=read();n=read();int t=0;
        rep(1,n) {
            char t1,t2;int x1,x2;
            t1=getc();x1=read();t2=getc();x2=read();
            if(t1==t2) ans+=abs(x1-x2);
            else A[++t]=(Point){x1,x2};
        }
        n=t;sort(A+1,A+n+1);ans+=n;
        if(k==1) {
            t=0;
            rep(1,n) tmp[t++]=A[i].x1,tmp[t++]=A[i].x2;
            sort(tmp,tmp+t);
            rep(0,t-1) ans+=abs(tmp[t/2]-tmp[i]);
            printf("%lld
    ",ans);
            return 0;
        }
        ToT=root=0;
        rep(1,n) {
            insert(root,0,1000000000,A[i].x1);insert(root,0,1000000000,A[i].x2);
            f[i]=query(root);
        }
        ToT=root=0;
        for(int i=n;i;i--) {
            g[i]=query(root);
            insert(root,0,1000000000,A[i].x1);insert(root,0,1000000000,A[i].x2);
        }
        rep(1,n) mn=min(mn,f[i]+g[i]);if(!n) mn=0;
        printf("%lld
    ",ans+mn);
        return 0;
    }
    View Code
  • 相关阅读:
    IO流
    集合中的工具类Collections和Arrays
    排序 查找
    函数及数组
    变量、静态的和单例模式
    java流程控制
    configure使用
    --sysroot
    LD_PRELOAD
    Linux下内存检测工具:asan :编译-连接-运行选项
  • 原文地址:https://www.cnblogs.com/wzj-is-a-juruo/p/4655531.html
Copyright © 2011-2022 走看看