[loj3364]植物比较

结论:设$b_{i}$满足该限制,则$a_{i}$合法当且仅当$\forall i\ne j,a_{i}\ne a_{j}$且$\forall |i-j|<k,[a_{i}<a_{j}]=[b_{i}<b_{j}]$,即$r_{i}$可以确定任意连续$k$位的相对大小关系

充分性显然成立,必要性不会证QAQ

构造$b_{i}$:考虑从0到$n-1$依次填写,每次填写的位置$x$需要满足:1.$r_{x}=k-1$;2.$\forall i-k<j<i,r_{j}\ne k-1$

第一个条件能够保证之后的$k-1$个数都比其小,第二个条件能保证之前的$k-1$个数都比其小(令$y$为前$k-1$个数中的最小值,再反证即可),因此这样是正确的

对于第2个条件的判定,可以找出所有满足$r_{x}=k-1$的点组成一个set,在对这个set插入或删除的同时,找出所有满足第2个条件的点再组成一个set(因为还要删除)即可

找到这样的位置后,填上当前的数,并令:1.$r_{x}=-\infty$(保证自己不再被选);2.$\forall i-k<j<i,r_{j}+=1$

建图:对于每一个数$i$,设其前$k-1$个数中前驱后继为$pre$和$nex$,连有向边$(nex,i)$和$(i,pre)$,之后$a_{x}>a_{y}$当且仅当$x$能走到$y$

虽然这张图并不一定是一条链,但不妨将所有边分为两类,向前(即$(nex,i)$)和向后(即$(i,pre)$)(并不是仅仅比较两数大小),那么如果存在路径,必然存在一条只走向前/向后的路径,使得能够到达$y$周围的$k$个位置,因此对两种路径分别倍增维护即可

  1 #include "plants.h"
  2 #include<bits/stdc++.h>
  3 using namespace std;
  4 #define N 200005
  5 #define oo 0x3f3f3f3f
  6 #define L (k<<1)
  7 #define R (L+1)
  8 #define mid (l+r>>1)
  9 set<int>se;
 10 set<int>::iterator itt;
 11 set<pair<int,int> >s;
 12 set<pair<int,int> >::iterator it;
 13 int n,k,a[N],r[N],tag[N<<2],f[N<<2],fa[2][N][21],d[2][N][21];
 14 void upd(int k,int x){
 15     tag[k]+=x;
 16     f[k]+=x;
 17 }
 18 void down(int k){
 19     upd(L,tag[k]);
 20     upd(R,tag[k]);
 21     tag[k]=0;
 22 }
 23 void update(int k,int l,int r,int x,int y,int z){
 24     if ((l>y)||(x>r))return;
 25     if ((x<=l)&&(r<=y)){
 26         upd(k,z);
 27         return;
 28     }
 29     down(k);
 30     update(L,l,mid,x,y,z);
 31     update(R,mid+1,r,x,y,z);
 32     f[k]=max(f[L],f[R]);
 33 }
 34 int query(int k,int l,int r){
 35     if (l==r)return l;
 36     down(k);
 37     if (f[L]==f[k])return query(L,l,mid);
 38     return query(R,mid+1,r);
 39 }
 40 bool pd(int x){
 41     if (x>=k-1)return (*se.upper_bound(x-k))==x;
 42     return (x==(*se.begin()))&&(se.upper_bound(x-k+n)==se.end());
 43 }
 44 void add(int x){
 45     itt=se.upper_bound(x);
 46     if (itt==se.end())itt=se.begin();
 47     int y=(*itt);
 48     if (pd(y))s.erase(make_pair(y,0));
 49     se.insert(x);
 50     if (pd(x))s.insert(make_pair(x,0));
 51     if (pd(y))s.insert(make_pair(y,0));
 52 }
 53 void del(int x){
 54     se.erase(x);
 55     itt=se.upper_bound(x);
 56     if (itt==se.end())itt=se.begin();
 57     if (pd(*itt))s.insert(make_pair((*itt),0));
 58 }
 59 int dis(int x,int y){
 60     if (x<=y)return y-x;
 61     return y+n-x;
 62 }
 63 void init(int kk,vector<int>rr){
 64     n=rr.size();
 65     k=kk;
 66     for(int i=0;i<n;i++)r[i]=rr[i];
 67     for(int i=0;i<n;i++)update(1,0,n-1,i,i,r[i]);
 68     for(int i=0;i<n;i++){
 69         while (f[1]==k-1){
 70             int x=query(1,0,n-1);
 71             add(x);
 72             update(1,0,n-1,x,x,-oo);
 73         }
 74         int x=(*s.begin()).first;
 75         s.erase(s.begin());
 76         del(x);
 77         a[x]=i;
 78         if (x-k+1>=0)update(1,0,n-1,x-k+1,x-1,1);
 79         else{
 80             update(1,0,n-1,0,x-1,1);
 81             update(1,0,n-1,x-k+1+n,n-1,1);
 82         }
 83     }
 84     for(int i=0;i<k;i++)s.insert(make_pair(a[i],i));
 85     for(int i=0;i<n;i++){
 86         s.erase(make_pair(a[i],i));
 87         it=upper_bound(s.begin(),s.end(),make_pair(a[i],i));
 88         if (it==s.end())fa[0][i][0]=i;
 89         else fa[0][i][0]=(*it).second;
 90         d[0][i][0]=dis(i,fa[0][i][0]);
 91         it=upper_bound(s.begin(),s.end(),make_pair(a[(i+k)%n],(i+k)%n));
 92         if (it==s.end())fa[1][(i+k)%n][0]=(i+k)%n;
 93         else fa[1][(i+k)%n][0]=(*it).second;
 94         d[1][(i+k)%n][0]=dis(fa[1][(i+k)%n][0],(i+k)%n);
 95         s.insert(make_pair(a[(i+k)%n],(i+k)%n));
 96     }
 97     for(int p=0;p<2;p++)
 98         for(int i=1;i<=20;i++)
 99             for(int j=0;j<n;j++){
100                 fa[p][j][i]=fa[p][fa[p][j][i-1]][i-1];
101                 d[p][j][i]=min(d[p][j][i-1]+d[p][fa[p][j][i-1]][i-1],n);
102             }
103 }
104 bool pd(int x,int y){
105     int dd=dis(x,y),z=x;
106     for(int i=20;i>=0;i--)
107         if (d[0][x][i]<=dd){
108             dd-=d[0][x][i];
109             x=fa[0][x][i];
110         }
111     if ((dd<k)&&(a[x]<=a[y]))return 1;
112     dd=dis(y,x=z);
113     for(int i=20;i>=0;i--)
114         if (d[1][x][i]<=dd){
115             dd-=d[1][x][i];
116             x=fa[1][x][i];
117         }
118     return ((dd<k)&&(a[x]<=a[y]));
119 }
120 int compare_plants(int x,int y){
121     if ((a[x]<a[y])&&(pd(x,y)))return -1;
122     if ((a[x]>a[y])&&(pd(y,x)))return 1;
123     return 0;
124 }
View Code

 

posted @ 2020-10-14 08:29  PYWBKTDA  阅读(127)  评论(0编辑  收藏  举报