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

    $n leq 500000$个数字,给实数$k$,问用这些数字填上的,满足$d_i geq d_{left lfloor frac{i}{k} ight floor}$的字典序最大的序列。

    如果数字不同的话按后序遍历从大到小填就行了。

    如果数字相同的话就不行。比如输入4 2 1 1 1 2。

    预定。每选一个数,要预定几个比他大的数。首先从小到大排序。

    方法零:线段树上维护每个数选了没选。在同一层的时候,每选一个数,就预定他左边紧贴着他的,他子树大小个数的数字。然后这层选完再把它还原回去。用个可持久化可以还原回去。难写。

    方法一:线段树上维护每个数右边有几个数还没预定。每次找数需要找一个x,满足x左边的“未预定数”都大于等于x的子树大小,找权值尽量大的、同权值尽量靠左的数字选中。选完后,把它左边所有数的“未预定数”减去他的子树大小。决定一个点时取消它父亲的影响,注意只用取消一次。

      1 //#include<iostream>
      2 #include<cstring>
      3 #include<cstdio>
      4 //#include<time.h>
      5 //#include<complex>
      6 //#include<queue>
      7 #include<algorithm>
      8 #include<stdlib.h>
      9 using namespace std;
     10 
     11 #define LL long long
     12 int qread()
     13 {
     14     char c; int s=0; while ((c=getchar())<'0' || c>'9');
     15     do s=s*10+c-'0'; while ((c=getchar())>='0' && c<='9'); return s;
     16 }
     17 
     18 //Pay attention to '-' , LL and double of qread!!!!
     19 
     20 int n; double K;
     21 #define maxn 500011
     22 int num[maxn];
     23 struct Edge{int to,next;}edge[maxn]; int first[maxn],le=2;
     24 void in(int x,int y) {Edge &e=edge[le]; e.to=y; e.next=first[x]; first[x]=le++;}
     25 
     26 int size[maxn];
     27 void dfs(int x)
     28 {
     29     size[x]=1;
     30     for (int i=first[x];i;i=edge[i].next)
     31     {
     32         Edge &e=edge[i];
     33         dfs(e.to); size[x]+=size[e.to];
     34     }
     35 }
     36 
     37 struct SMT
     38 {
     39     struct Node{int ls,rs; int Min,add;}a[maxn<<1];
     40     int size,n;
     41     void up(int x) {a[x].Min=min(a[a[x].ls].Min,a[a[x].rs].Min);}
     42     void build(int &x,int L,int R)
     43     {
     44         x=++size;
     45         if (L==R) {a[x].Min=n-L; return;}
     46         int mid=(L+R)>>1;
     47         build(a[x].ls,L,mid); build(a[x].rs,mid+1,R);
     48         up(x);
     49     }
     50     void build(int m) {n=m; size=0; int x; build(x,1,n);}
     51     
     52     void addsingle(int x,int v) {a[x].add+=v; a[x].Min+=v;}
     53     void down(int x) {if (a[x].add) {addsingle(a[x].ls,a[x].add); addsingle(a[x].rs,a[x].add); a[x].add=0;}}
     54     
     55     int ql,qr,v;
     56     void Add(int x,int L,int R)
     57     {
     58         if (ql<=L && R<=qr) {addsingle(x,v); return;}
     59         down(x);
     60         int mid=(L+R)>>1;
     61         if (ql<=mid) Add(a[x].ls,L,mid);
     62         if (qr>mid) Add(a[x].rs,mid+1,R);
     63         up(x);
     64     }
     65     void add(int L,int R,int v) {if (L>R) return; ql=L; qr=R; this->v=v; Add(1,1,n);}
     66     
     67     int Query(int x,int L,int R)
     68     {
     69         if (L==R) return L;
     70         down(x);
     71         int mid=(L+R)>>1;
     72         if (a[a[x].ls].Min>=v) return Query(a[x].rs,mid+1,R);
     73         return Query(a[x].ls,L,mid);
     74     }
     75     int query(int val) {v=val; return Query(1,1,n);}
     76     
     77     int Find(int x,int L,int R)
     78     {
     79         if (L==R) return L;
     80         down(x);
     81         int mid=(L+R)>>1;
     82         if (num[mid]>=v) return Find(a[x].ls,L,mid);
     83         return Find(a[x].rs,mid+1,R);
     84     }
     85     int find(int val) {v=val; return Find(1,1,n);}
     86     
     87 }t;
     88 
     89 int ans[maxn],fa[maxn];
     90 int main()
     91 {
     92     n=qread(); scanf("%lf",&K);
     93     for (int i=1;i<=n;i++) num[i]=qread();
     94     
     95     fa[0]=-1;
     96     for (int i=1;i<=n;i++) in(fa[i]=(int)(i/K+1e-9),i);
     97     dfs(0);
     98     
     99     sort(num+1,num+1+n); num[++n]=0x3f3f3f3f;
    100     t.build(n);
    101     for (int i=1;i<n;i++)
    102     {
    103         if (fa[i] && fa[i]!=fa[i-1]) t.add(1,ans[fa[i]],size[fa[i]]-1);
    104         int val=num[t.query(size[i])-1]; int p=t.find(val);
    105         ans[i]=p; t.add(1,ans[i],-size[i]);
    106     }
    107     
    108     for (int i=1;i<n;i++) printf("%d ",num[ans[i]]);
    109     return 0;
    110 }
    View Code

    方法二:看不太懂

  • 相关阅读:
    java基础——DecimalFormat
    剑指——重建二叉树
    error error: illegal character: 'u3000'
    Android: Unhandled exception java.net.malformedurlexception 异常笔记
    Android获取系统时间
    java基础——hashCode笔记
    golang 红黑树
    golang 实现跳表skiplist
    快排
    堆排序
  • 原文地址:https://www.cnblogs.com/Blue233333/p/8880806.html
Copyright © 2011-2022 走看看