bzoj 4345 [POI2016]Korale

可能是我数据结构学傻了。

显然序列长度不超过$logK$。

然后我就掉在了$O(n*log^2n)$的坑里。

正解居然是dfs.....

第一问直接二分,然后dfs找答案,注意是在排完序之后的序列上找,这样保证是$O(K)$的复杂度。

然后第二问我又不会了,我一直在想怎么按位确定,也只能做到$O(n*log^2n)$。

直接dfs......但是序列不是有序的了。直接线段树找下一个pos就行了,显然这样找到的序列个数是K的。

复杂度是$O(n*logw+n*logn)$的。

#include <bits/stdc++.h>
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
#define for1(a,b,i) for(int i=a;i<=b;++i)
#define FOR2(a,b,i) for(int i=a;i>=b;--i)
using namespace std;
typedef long long ll;
inline int read() {
    int f=1,sum=0;
    char x=getchar();
    for(;(x<'0'||x>'9');x=getchar()) if(x=='-') f=-1;
    for(;x>='0'&&x<='9';x=getchar()) sum=sum*10+x-'0';
    return f*sum;
}
 
#define M 1000005
int n,K;
ll mid,ans;
int a[M],b[M],cnt,tot,val[M*4],sta[M];

inline void dfs(int x,ll sum) {
    if(x==n+1) return;
    if(b[x]+sum>mid) return;
    ++cnt;
    if(cnt==K) return;
    dfs(x+1,sum);
    if(cnt==K) return;
    dfs(x+1,sum+b[x]);
}

inline void build(int g,int l,int r) {
    if(l==r) return val[g]=a[l],void();
    int mid=l+r>>1;
    build(g<<1,l,mid);
    build(g<<1|1,mid+1,r);
    val[g]=min(val[g<<1],val[g<<1|1]);
}

inline int query(int g,int l,int r,int lx,int rx,ll x) {
    if(val[g]>x) return 0;
    if(lx>r||rx<l) return 0;
    if(l==r) return l;
    int mid=l+r>>1;
    int num=query(g<<1,l,mid,lx,rx,x);
    if(num) return num;
    return query(g<<1|1,mid+1,r,lx,rx,x);
}

inline void Dfs(int x,ll sum) {
    if(!sum) {
        --tot;
        if(!tot) {
            for1(1,sta[0],i) printf("%d ",sta[i]);
            puts("");
            exit(0);
        }
    }
    for(int i=x;i;) {
        int pos=query(1,1,n,i,n,sum);
        if(!pos) return;
        sta[++sta[0]]=pos;
        Dfs(pos+1,sum-a[pos]);
        --sta[0];
        i=pos+1;
    }
}

int main () {
    n=read(),K=read()-1;
    if(!K) return printf("0\n\n"),0;
    for1(1,n,i) a[i]=b[i]=read();
    sort(b+1,b+n+1);
    
    ll l=1,r=0;
    for1(1,20,i) r+=b[i];
    while (l<=r) {
        mid=l+r>>1;
        cnt=0;
        dfs(1,0);
        if(cnt==K) ans=mid,r=mid-1;
        else l=mid+1;
    }
    printf("%lld\n",ans);
    cnt=0,mid=ans-1,dfs(1,0),tot=K-cnt;
    build(1,1,n);
    Dfs(1,ans);
}
posted @ 2018-09-13 18:30  asd123www  阅读(305)  评论(0编辑  收藏  举报