• bzoj4881 [ Lydsy2017年5月月赛 ] -- 二分图染色+线段树


    以下是Claris的题解:

    若线段 i j 相交,那么在它们之间连一条边。若这个图不是二分图,那么无解,否则令cnt 为连通块个数,那么 ans = 2cnt

    在二分图染色的过程中,每个点只需要被访问一次。对于当前所在的点 x,它可以一步走到 [1, x) 里 p[i] > p[x] 的所有 i,以及 (x, n] 里 p[j] < p[x] 的所有 j。

    用线段树维护所有没走过的点,记录每个区间 p 最小与最大的两个位置。每次贪心取出最大/小的,看看是否满足条件,

    若满足则删除该点,然后递归染色,否则终止。
    时间复杂度 O(n log n)。

    代码:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 using namespace std;
     6 #define N 100010
     7 #define M 998244353
     8 #define INF 1000000
     9 int i,j,k,n,m,p[N],c[2][N<<2],s[2][N<<2],Cnt,f[2];
    10 bool a[N],v[N];
    11 inline int Min(int x,int y){return x<y?x:y;}
    12 inline int Max(int x,int y){return x<y?y:x;}
    13 inline void Up(int Node){
    14     c[0][Node]=Min(c[0][Node<<1],c[0][Node<<1|1]);
    15     s[0][Node]=c[0][Node]==c[0][Node<<1]?s[0][Node<<1]:s[0][Node<<1|1];
    16     c[1][Node]=Max(c[1][Node<<1],c[1][Node<<1|1]);
    17     s[1][Node]=c[1][Node]==c[1][Node<<1]?s[1][Node<<1]:s[1][Node<<1|1];
    18 }
    19 inline void Update(int Node,int l,int r,int x){
    20     if(l==r){
    21         c[0][Node]=INF;
    22         c[1][Node]=s[0][Node]=s[1][Node]=0;
    23         return;
    24     }
    25     int Mid=l+r>>1;
    26     if(x<=Mid)Update(Node<<1,l,Mid,x);else Update(Node<<1|1,Mid+1,r,x);
    27     Up(Node);
    28 }
    29 inline int Query(int Node,int l,int r,int L,int R,bool d){
    30     if(l>=L&&r<=R)return s[d][Node];
    31     int Mid=l+r>>1;
    32     if(Mid<L)return Query(Node<<1|1,Mid+1,r,L,R,d);
    33     if(Mid>=R)return Query(Node<<1,l,Mid,L,R,d);
    34     int Q1=Query(Node<<1,l,Mid,L,R,d),Q2=Query(Node<<1|1,Mid+1,r,L,R,d);
    35     if(Q1&&(d^(p[Q1]<p[Q2]?1:0)))return Q1;return Q2;
    36 }
    37 inline void Dfs(int x){
    38     v[x]=1;
    39     Update(1,1,n,x);
    40     while(1){
    41         if(x>1){
    42             int y=Query(1,1,n,1,x-1,1);
    43             if(y&&p[y]>p[x]){
    44                 a[y]=a[x]^1;
    45                 Dfs(y);
    46                 continue;
    47             }
    48         }
    49         if(x<n){
    50             int y=Query(1,1,n,x+1,n,0);
    51             if(y&&p[y]<p[x]){
    52                 a[y]=a[x]^1;
    53                 Dfs(y);
    54                 continue;
    55             }
    56         }
    57         break;
    58     }
    59 }
    60 inline int Pow(int x,int y){
    61     if(y==0)return 1;
    62     int Ans=Pow(x,y>>1);
    63     Ans=1ll*Ans*Ans%M;
    64     if(y&1)Ans=1ll*Ans*x%M;
    65     return Ans;
    66 }
    67 inline void Build(int Node,int l,int r){
    68     if(l==r){
    69         scanf("%d",&p[l]);
    70         c[0][Node]=c[1][Node]=p[l];
    71         s[0][Node]=s[1][Node]=l;
    72         return;
    73     }
    74     int Mid=l+r>>1;
    75     Build(Node<<1,l,Mid);
    76     Build(Node<<1|1,Mid+1,r);
    77     Up(Node);
    78 }
    79 int main(){
    80     scanf("%d",&n);
    81     Build(1,1,n);
    82     for(i=1;i<=n;i++)
    83     if(!v[i])a[i]=1,Dfs(i),Cnt++;
    84     for(i=1;i<=n;i++)
    85     if(f[a[i]]>p[i]){puts("0");return 0;}else f[a[i]]=p[i];
    86     printf("%d
    ",Pow(2,Cnt));
    87     return 0;
    88 }
    bzoj4881
  • 相关阅读:
    Conv2 GPU加速(有代码有图有真相)
    OpenACC指令适不适合我的程序吗?
    MongoDBHelper
    Js事件 事件绑定
    xslt元素 applyimports
    博客成立,开启一段追逐之旅,留个小小的纪念 ^^
    函数
    C语言基本特性
    预处理
    数组
  • 原文地址:https://www.cnblogs.com/gjghfd/p/6820310.html
Copyright © 2020-2023  润新知