zoukankan      html  css  js  c++  java
  • [bzoj5249][2018多省省队联测]IIIDX

    给我的感觉是需要先言传才能意会。。。真的可以在考场上想到这么神的算法吗??

    #include<bits/stdc++.h>
    using namespace std;
    const int N=500010;
    const int inf=1e9;
    inline int read(){
        int r=0,c=getchar();
        while(!isdigit(c))c=getchar();
        while(isdigit(c))
        r=r*10+c-'0',c=getchar();
        return r;
    }
    struct Edge{
        int to,nxt;
    }e[N<<1];
    int head[N],cnt=1;
    void add(int u,int v){
        e[cnt]=(Edge){v,head[u]};
        head[u]=cnt++;
    }
    int n;double k;
    int a[N],b[N],las[N],fa[N],siz[N];
    void dfs(int u){
        siz[u]=1;
        for(int i=head[u];i;i=e[i].nxt){
            int v=e[i].to;
            dfs(v);siz[u]+=siz[v];
        }
    }
    struct Node{
        int l,r,add,mn;
    }T[N<<2];
    #define ls o<<1
    #define rs o<<1|1
    #define L T[o].l
    #define R T[o].r
    #define M (L+R>>1)
    void pp(int o){
        T[o].mn=min(T[ls].mn,T[rs].mn);
    }
    void pd(int o){
        if(T[o].add){
            T[ls].add+=T[o].add;
            T[rs].add+=T[o].add;
            T[ls].mn+=T[o].add;
            T[rs].mn+=T[o].add;
            T[o].add=0;
        }
    }
    void build(int o,int l,int r){
        if(l==r){
            T[o]=(Node){l,r,0,l};
            return;
        }
        T[o]=(Node){l,r,0,inf};
        build(ls,L,M);
        build(rs,M+1,R);
        pp(o);
    }
    int ql,qr,v;
    void upd(int o){
        if(ql<=L&&R<=qr){
            T[o].add+=v;
            T[o].mn+=v;
            return;
        }
        pd(o);
        if(ql<=M)upd(ls);
        if(qr>M) upd(rs);
        pp(o);
    }
    int find(int o){
        if(L==R)return T[o].mn>=v?L:L+1;
        pd(o);
        if(T[rs].mn>=v)return find(ls);
        else return find(rs);
    }
    bool comp(int p,int q){
        return p>q;
    }
    void init(){
        n=read();cin>>k;
        for(int i=1;i<=n;i++){
            fa[i]=(double)i/k+1e-10;//浮点数有坑 
            add(fa[i],i);b[i]=read();
        }
        sort(b+1,b+n+1,comp);
        for(int i=1;i<=n;i++)
        if(b[i]==b[i-1])
        a[i]=a[i-1],las[a[i]]=i;
        else a[i]=i,las[a[i]]=i;
        dfs(0);
    }
    int ans[N],vis[N];
    void solve(){
        build(1,1,n);//建线段树,i的初值为i 
        for(int i=1;i<=n;i++){
            if(fa[i]&&!vis[fa[i]]){//如果父亲的预定没被撤销 
                vis[fa[i]]=1;//只撤销一次所以要标记一下 
                ql=ans[fa[i]],qr=n;
                v=siz[fa[i]]-1;upd(1);//父亲修改的区间加上siz[fa]-1 
            }
            v=siz[i];int x=a[find(1)];//在线段树上二分查找第一个右侧值及本身全部大于等于siz[i]的结点
            v=-v;ans[i]=ql=las[x]--,qr=n;upd(1);//值已经确定,选择最靠右的那个,并把它及它右边的值减去siz[i] 
        }
        for(int i=1;i<=n;i++)
        printf("%d ",b[ans[i]]);
    }
    int main(){
        init();
        solve();
    }
  • 相关阅读:
    两种常用的jquery事件加载的方法 的区别
    .net修炼笔记
    C#获取MySql 数据常用的代码
    sql时间格式化
    UMEditor(Ueditor mini)修改图片上传路径
    LeetCode_101. Symmetric Tree
    LeetCode_100. Same Tree
    LeetCode_88. Merge Sorted Array
    LeetCode_83. Remove Duplicates from Sorted List
    LeetCode_70. Climbing Stairs
  • 原文地址:https://www.cnblogs.com/orzzz/p/8794539.html
Copyright © 2011-2022 走看看