• [loj6518]序列


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

    首先题目有一个条件似乎没有写出来,是保证$lle kle 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
  • 相关阅读:
    网站描述description如何编写
    网站关键词布局设置,这样添加关键词排名很容易上来!
    长尾关键词挖掘工具和使用方法
    小站点如何做好长尾词库(600个长尾词排名的经验分享!)
    如何利用seo技术霸屏你的行业关键词排名
    利用seo技术排名热点新闻词引流(日IP增加2万+)
    yagmail模块的使用
    python--接口自动化
    Python--unittest参数化
    Python--日志模块
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/14292275.html
Copyright © 2020-2023  润新知