[loj6518]序列

参考ExtremeSpanningTrees,考虑优化整体二分时求$g_{i}\in \{w_{mid},w_{mid+1}\}$的最优解

首先题目有一个条件似乎没有写出来,是保证$l\le k\le r$的(但并不是特别重要,可能更方便)

可以发现只关心于$k$属于当前考虑的点集中的询问即可,因此每一次层的限制数为$o(m)$(可以通过上面的条件,将区间求并后优化为$o(n)$个)

考虑用线段树来优化建图,具体来说,分为以下几步:

1.将点以及区间离散到点个数长度的区间,来保证复杂度;

2.建两颗线段树,左边的线段树从儿子到父亲,右边的线段树从父亲到儿子(流量inf)

3.每一个点连向左边对应的叶子,右边的叶子连向对应的点,根据权值划分到$S$和$T$

4.对于初始$k$到$[l,r]$的边,对应为$k$在左边的叶子连向右边$[l,r]$对应的log个区间,反之类似

理论时间复杂度为$o(n^{3}\log^{2}n)$,可以通过

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 #define N 5005
  4 #define ll long long
  5 #define oo 0x3f3f3f3f
  6 #define vi vector<int>
  7 #define L (k<<1)
  8 #define R (L+1)
  9 struct ji{
 10     int nex,to,len;
 11 }edge[N<<5];
 12 queue<int>q;
 13 int n,m,p,l,r,k,lx[N][2],rx[N][2],w[N],v[N],a[N],ans[N];
 14 int V,E,leaf[N],head[N<<4],work[N<<4],d[N<<4],vis[N<<4],bl[N];
 15 bool cmp(int x,int y){
 16     return (bl[x]<bl[y])||(bl[x]==bl[y])&&(x<y);
 17 }
 18 void add(int x,int y,int z){
 19     edge[E].nex=head[x];
 20     edge[E].to=y;
 21     edge[E].len=z;
 22     head[x]=E++;
 23     if (E&1)add(y,x,0);
 24 }
 25 bool bfs(){
 26     memset(d,oo,sizeof(d));
 27     d[0]=0;
 28     q.push(0);
 29     while (!q.empty()){
 30         int k=q.front();
 31         q.pop();
 32         for(int i=head[k];i!=-1;i=edge[i].nex)
 33             if ((edge[i].len)&&(d[edge[i].to]==oo)){
 34                 d[edge[i].to]=d[k]+1;
 35                 q.push(edge[i].to);
 36             }
 37     }
 38     return d[(V<<1)+n+1]<oo;
 39 }
 40 int dfs(int k,int s){
 41     if (k>(V<<1)+n)return s;
 42     for(int &i=work[k];i!=-1;i=edge[i].nex)
 43         if ((edge[i].len)&&(d[edge[i].to]==d[k]+1)){
 44             int p=dfs(edge[i].to,min(s,edge[i].len));
 45             if (p){
 46                 edge[i].len-=p;
 47                 edge[i^1].len+=p;
 48                 return p;
 49             }
 50         }
 51     return 0;
 52 }
 53 void dinic(){
 54     while (bfs()){
 55         memcpy(work,head,sizeof(work));
 56         while (dfs(0,oo));
 57     }
 58 }
 59 void dfs(int k){
 60     if (vis[k])return;
 61     vis[k]=1;
 62     for(int i=head[k];i!=-1;i=edge[i].nex)
 63         if (edge[i].len)dfs(edge[i].to);
 64 }
 65 void build(int k,int l,int r){
 66     if (l==r){
 67         leaf[l]=k;
 68         V=max(V,k);
 69         return;
 70     }
 71     int mid=(l+r>>1);
 72     build(L,l,mid);
 73     build(R,mid+1,r);
 74 }
 75 void update(int k,int l,int r,int x,int y,int z,int p){
 76     if ((l>y)||(x>r))return;
 77     if ((x<=l)&&(r<=y)){
 78         if (p)add(k,z+V,oo);
 79         else add(z,k+V,oo);
 80         return;
 81     }
 82     int mid=(l+r>>1);
 83     update(L,l,mid,x,y,z,p);
 84     update(R,mid+1,r,x,y,z,p);
 85 }
 86 void dfs(int l,int r,int x,int y){
 87     if (x==y){
 88         for(int i=l;i<=r;i++)ans[a[i]]=v[x];
 89         return;
 90     }
 91     int mid=(x+y>>1);
 92     V=E=0;
 93     build(1,1,r-l+1);
 94     for(int i=0;i<=(V<<1)+n+1;i++)head[i]=-1;
 95     for(int i=2;i<=V;i++){
 96         add(i,i/2,oo);
 97         add(i/2+V,i+V,oo);
 98     }
 99     for(int i=l;i<=r;i++){//若i比j小则i向j连边,源点连大的,汇点连小的 
100         add((V<<1)+i,leaf[i-l+1],oo);
101         add(leaf[i-l+1]+V,(V<<1)+i,oo);
102         if (w[a[i]]>=v[mid+1])add(0,(V<<1)+i,1);
103         else add((V<<1)+i,(V<<1)+n+1,1);
104     }
105     for(int i=l;i<=r;i++)
106         for(int j=0;j<2;j++){
107             int x=lx[a[i]][j],y=rx[a[i]][j];
108             int wx=lower_bound(a+l,a+r+1,x)-a-l+1,wy=upper_bound(a+l,a+r+1,y)-a-l;
109             if (wx<wy)update(1,1,r-l+1,wx,wy,leaf[i-l+1],j);
110         }
111     dinic();
112     for(int i=0;i<=(V<<1)+n+1;i++)vis[i]=0;
113     dfs(0);
114     for(int i=l;i<=r;i++){
115         if ((w[a[i]]>=v[mid+1])&&(vis[leaf[i-l+1]])||(w[a[i]]<v[mid+1])&&(vis[leaf[i-l+1]+V]))bl[a[i]]=1;
116         else bl[a[i]]=0;
117     }
118     sort(a+l,a+r+1,cmp);
119     for(int i=l;i<=r+1;i++){
120         if ((bl[a[i]])||(i>r)){
121             if (l<i)dfs(l,i-1,x,mid);
122             if (i<=r)dfs(i,r,mid+1,y);
123             return;
124         }
125     }
126 }
127 int main(){
128     scanf("%d%d",&n,&m);
129     for(int i=1;i<=n;i++)scanf("%d",&w[i]);
130     for(int i=1;i<=n;i++)
131         for(int j=0;j<2;j++)lx[i][j]=rx[i][j]=i;
132     for(int i=1;i<=m;i++){
133         scanf("%d%d%d%d",&p,&l,&r,&k);
134         lx[k][p]=min(lx[k][p],l);
135         rx[k][p]=max(rx[k][p],r);
136     } 
137     memcpy(v,w,sizeof(v));
138     sort(v+1,v+n+1);
139     int nn=unique(v+1,v+n+1)-v-1;
140     for(int i=1;i<=n;i++)a[i]=i;
141     dfs(1,n,1,nn);
142     long long sum=0;
143     for(int i=1;i<=n;i++)sum+=abs(ans[i]-w[i]);
144     for(int i=1;i<=n;i++){
145         for(int j=lx[i][0];j<=rx[i][0];j++)assert(ans[j]>=ans[i]);
146         for(int j=lx[i][1];j<=rx[i][1];j++)assert(ans[j]<=ans[i]);
147     }
148     printf("%lld",sum);
149 }
View Code

 

posted @ 2021-01-18 13:31  PYWBKTDA  阅读(121)  评论(0编辑  收藏  举报