• JZOJ5146:港湾


    Description

    放假啦!
    小林和康娜来到了港口,看到有货船正在卸货。
    港口十分狭窄,只有两个卸货区可以使用。每个卸货区上面可以堆积任意多个箱子。
    每卸下来一个箱子,工作人员都会把这个箱子放在某个卸货区的顶端。之后,当车辆来运走这个箱子的时候,也必须保证这个箱子在某个卸货区的顶端。
    港口今天一共运来了N个箱子,第i个箱子在时刻Ai被卸货,在时刻Bi被取走。康娜发现,每个箱子被取走时,都恰好位于所在卸货区的顶端。
    康娜觉得很有意思,她想要知道,有多少种卸货方案,使得每个箱子在被取走时都位于所在卸货区的顶端呢?
    两种方案不同,当且仅当存在一个箱子,使得在两个方案中这个箱子被放在了不同的卸货区。

    Input

    第一行一个正整数N,表示箱子的数量。
    接下来N行,每行两个空格分割的正整数Ai和Bi,表示第i个箱子在时刻Ai被卸货,在时刻Bi被取走。

    Output

    输出一行一个非负整数,表示合法的卸货方案。由于这个数字可能过大,你只需要输出方案数对1,000,000,007的模数即可。

    Sample Input

    4

    1 3

    2 5

    4 8

    6 7

    Sample Output

    4

    HINT

    对于10%的数据,N<=20
    对于30%的数据,N<=2000
    对于100%的数据,
    1<=N<=10^5
    1<=Ai<Bi<=2N
    A1,A2,...,AN,B1,B2,...,BN构成1...2N的一个排列。
     
    题解:
    如果两个物品i,j不能放在一个卸货区上(即 a[i]<a[j]<b[i]<b[j] or a[j]<a[i]<b[j]<b[i]),则记为i与j冲突,在i与j之间连一条边。
    这样建出了一个无向图,若其能二分图染色,则存在方案,为2^(连通块个数)。
    如果暴力建图,则复杂度为O(n^2),不可行。
    考虑用带权并查集,每个点支持查询祖先以及其与祖先染色是否相同,就可以维护连通块了。
    现在的问题是如何去掉重复意义的边。
    我们可以用线段树套vector来维护右端点在[l,r]之间的物品。这些物品代表的是其所属的并查集以及其在并查集中的染色。若某个vector中的两个物品代表的意义相同,则可以只留一个。
    我们把物品按照左端点排序,按顺序插入线段树,则前i-1个物品中,右端点在[a[i]+1,b[i]-1]的物品都与物品i冲突。
    这些物品可以在线段树区间[a[i]+1,b[i]-1]中查询得到。我们把这些物品以及物品i所代表的并查集合在一起。
    若有两个物品代表的并查集相同,但是染色不同,则发生冲突,不可二分图染色,输出0。
    然后,我们清空区间[a[i]+1,b[i]-1]所用到的线段树节点的vector(这些物品现在都代表同一个并查集),根据清空前其中的物品代表的染色,最多重新放入两个。
    最后,我们在包含b[i]的线段树节点的vector中放入物品i。
    最后,输出ans=2^(并查集个数)。
     
    代码:
     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 vector <int> v[400005];
     4 int t[400005][4],n,fa[200005][2],bo[100005][2],cnt,nn,tot,now;
     5 pair <int,int> a[100005],b[200005];
     6 void build(int l,int r,int fa)
     7 {
     8     cnt++; int x=cnt; t[x][0]=l; t[x][1]=r; 
     9     if(t[x][0]==t[fa][0])t[fa][2]=x;else t[fa][3]=x;
    10     if(l==r)return;
    11     build(l,(l+r)/2,x); build((l+r)/2+1,r,x);
    12 }
    13 int get2(int x);
    14 int get1(int x)
    15 {
    16     if(fa[x][0]!=x){ int a=fa[x][0]; fa[x][0]=get1(a); fa[x][1]^=get2(a); }
    17     return fa[x][0];
    18 }
    19 int get2(int x)
    20 {
    21     if(fa[x][0]!=x){ int a=fa[x][0]; fa[x][0]=get1(a); fa[x][1]^=get2(a); }
    22     return fa[x][1];
    23 }
    24 void ss(int x,int l,int r)
    25 {
    26     if(l>r)return;
    27     int ll=t[x][0],rr=t[x][1]; int mid=(ll+rr)/2;
    28     if((ll==l)and(rr==r))
    29     {
    30         int mm=v[x].size();
    31         for(int i=0;i<mm;i++)
    32         {
    33             int aa=get1(v[x][i]),bb=get2(v[x][i]); int xxx=v[x][i];
    34             if(bo[aa][bb]==0){ bo[aa][bb]=1; nn++; b[nn]=make_pair(aa,bb); }
    35         }
    36         return;
    37     }
    38     if(r<=mid)ss(t[x][2],l,r);else
    39     if(l>mid)ss(t[x][3],l,r);else
    40     { ss(t[x][2],l,mid); ss(t[x][3],mid+1,r); }
    41 }
    42 void ss2(int x,int l,int r)
    43 {
    44     if(l>r)return;
    45     int ll=t[x][0],rr=t[x][1]; int mid=(ll+rr)/2;
    46     if((ll==l)and(rr==r))
    47     {
    48         int mm=v[x].size(),q[2]; q[0]=0; q[1]=0;
    49         for(int i=0;i<mm;i++)
    50         {
    51             int bb=get2(v[x][i]); 
    52             if(q[bb]==0)q[bb]=v[x][i];
    53         }
    54         v[x].clear(); 
    55         if(q[0]>0)v[x].push_back(q[0]); 
    56         if(q[1]>0)v[x].push_back(q[1]);
    57         return;
    58     }
    59     if(r<=mid)ss2(t[x][2],l,r);else
    60     if(l>mid)ss2(t[x][3],l,r);else
    61     { ss2(t[x][2],l,mid); ss2(t[x][3],mid+1,r); }
    62 }
    63 void ss3(int x,int l,int y)
    64 {
    65     int ll=t[x][0],rr=t[x][1]; int mid=(ll+rr)/2;
    66     v[x].push_back(y); if(ll==rr)return; 
    67     if(l<=mid)ss3(t[x][2],l,y);
    68     if(l>mid)ss3(t[x][3],l,y);
    69 }
    70 void hb(int x,int y,int z)
    71 {
    72     int a=get1(x); if(a==y)return; 
    73     fa[a][0]=y; fa[a][1]^=z; tot--;
    74 }
    75 int main()
    76 {
    77     freopen("port.in","r",stdin);
    78     freopen("port.out","w",stdout);
    79     scanf("%d",&n); tot=n;
    80     for(int i=1;i<=n;i++)scanf("%d%d",&a[i].first,&a[i].second),fa[i][0]=i;
    81     sort(a+1,a+n+1); build(1,2*n,0);
    82     for(int i=1;i<=n;i++)
    83     {
    84         nn=0; now=i;
    85         ss(1,a[i].first+1,a[i].second-1);
    86         sort(b+1,b+nn+1);
    87         for(int j=1;j<=nn;j++)
    88         {
    89             if((j>1)and(b[j].first==b[j-1].first)){ printf("0
    "); return 0; }
    90             hb(b[j].first,i,b[j].second^1); bo[b[j].first][b[j].second]=0;
    91         }
    92         ss2(1,a[i].first+1,a[i].second-1);
    93         ss3(1,a[i].second,i);
    94     }
    95     long long ans=1;
    96     for(int i=1;i<=tot;i++)ans=(ans*2)%1000000007;
    97     printf("%lld
    ",ans);
    98 }
    View Code
  • 相关阅读:
    android手机上的app输入法遮挡输入框问题
    简单的百度地图使用
    简单的加入购物车动画效果,需引入外部js文件
    vue项目中axios跨域设置
    一次讲清promise
    js中宏任务,微任务,异步,同步,执行的顺序
    vantUI <van-uploader> 上传图片,如何获取图片的尺寸
    Vue双向绑定原理 从vue2的Object.defineProperty到vue3的proxy
    微信浏览器h5页面开发遇到问题
    Web前端优化最佳实践及工具集锦
  • 原文地址:https://www.cnblogs.com/GhostReach/p/7015761.html
Copyright © 2020-2023  润新知