2017多校第4场 HDU 6070 Dirt Ratio 分数规划,线段树

来源:互联网 发布:js图片渐变轮换效果 编辑:程序博客网 时间:2024/05/08 02:36

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6070

题意:给个数列,问取一个子序列,子序列里面如果出现相同的数,计数器cnt +1,最后求所有的子序列中cnt/序列长度的最小值。

解法:SB题,我真的SBBBBBBBBBBBBBBBBBBB。。。被虐记。。。


#include <bits/stdc++.h>using namespace std;typedef long long LL;struct FastIO{    static const int S = 1310720;    int wpos;    char wbuf[S];    FastIO() : wpos(0) {}    inline int xchar()    {        static char buf[S];        static int len = 0, pos = 0;        if (pos == len)            pos = 0, len = fread(buf, 1, S, stdin);        if (pos == len) return -1;        return buf[pos ++];    }    inline int xuint()    {        int c = xchar(), x = 0;        while (c <= 32) c = xchar();        for (; '0' <= c && c <= '9'; c = xchar()) x = x * 10 + c - '0';        return x;    }    inline int xint()    {        int s = 1, c = xchar(), x = 0;        while (c <= 32) c = xchar();        if (c == '-') s = -1, c = xchar();        for (; '0' <= c && c <= '9'; c = xchar()) x = x * 10 + c - '0';        return x * s;    }    inline void xstring(char *s)    {        int c = xchar();        while (c <= 32) c = xchar();        for (; c > 32; c = xchar()) * s++ = c;        *s = 0;    }    inline void wchar(int x)    {        if (wpos == S) fwrite(wbuf, 1, S, stdout), wpos = 0;        wbuf[wpos ++] = x;    }    inline void wint(LL x)    {        if (x < 0) wchar('-'), x = -x;        char s[24];        int n = 0;        while (x || !n) s[n ++] = '0' + x % 10, x /= 10;        while (n--) wchar(s[n]);    }    inline void wstring(const char *s)    {        while (*s) wchar(*s++);    }    ~FastIO()    {        if (wpos) fwrite(wbuf, 1, wpos, stdout), wpos = 0;    }} io;const double eps = 1e-6;const int maxn = 60010;int n, last[maxn],a[maxn];struct node{    int l,r;    double val,add;}tree[maxn<<2];void pushup(int rt){    tree[rt].val=min(tree[rt*2].val,tree[rt*2+1].val);}void pushdown(int rt){    if(tree[rt].add){        tree[rt<<1].val=tree[rt<<1].val+tree[rt].add;        tree[rt<<1|1].val=tree[rt<<1|1].val+tree[rt].add;        tree[rt<<1].add+=tree[rt].add;        tree[rt<<1|1].add+=tree[rt].add;        tree[rt].add=0;    }}void build(int l,int r,int rt, double x){    tree[rt].l=l,tree[rt].r=r,tree[rt].add=0;    if(l==r){        tree[rt].val=1.0*x*l;        return;    }    int mid=(l+r)/2;    build(l,mid,rt*2,x);    build(mid+1,r,rt*2+1,x);    pushup(rt);}void update(int L,int R,double val, int rt){    if(L<=tree[rt].l&&tree[rt].r<=R){        tree[rt].val+=val;        tree[rt].add+=val;        return;    }    pushdown(rt);    int mid=(tree[rt].l+tree[rt].r)/2;    if(R<=mid) update(L,R,val,rt*2);    else if(L>mid) update(L,R,val,rt*2+1);    else{        update(L,mid,val,rt*2);        update(mid+1,R,val,rt*2+1);    }    pushup(rt);}double query(int L, int R, int rt){    if(L<=tree[rt].l&&tree[rt].r<=R){        return tree[rt].val;    }    pushdown(rt);    int mid=(tree[rt].l+tree[rt].r)/2;    if(R<=mid) return query(L,R,rt*2);    else if(L>mid) return query(L,R,rt*2+1);    else{        return min(query(L,mid,rt*2), query(mid+1,R,rt*2+1));    }}bool check(double mid){    for(int i=1; i<=n; i++) last[i]=0;    build(1,n,1,mid);    for(int i=1; i<=n; i++){        update(last[a[i]]+1,i,1.0,1);        double mi = query(1,i,1);        if((mi-mid*(i+1))<=0) return true;        last[a[i]]=i;    }    return false;}int main(){    int T;    T = io.xint();    while(T--){        n = io.xint();        for(int i=1; i<=n; i++){            a[i] = io.xint();        }        double l = 0, r = 1.0;        for(int i=0; i<20; i++){            double mid = (l+r)/2.0;            if(check(mid)) r=mid;            else l=mid;        }        printf("%.10f\n", (l+r)/2.0);    }    return 0;}


原创粉丝点击