zoukankan      html  css  js  c++  java
  • 【JOI2017春季合宿】Port Facility

    http://uoj.ac/problem/356

    题解

    思路和(NOIP)双栈排序差不多。

    对于两个元素,若(l_1<l_2<r_1<r_2)那么它们不能在一个栈里,我们连一条边。

    若最后的这张图是二分图,那么答案就是(2^{联通块个数})

    这道题就是要我们优化连边。

    我们把所有线段按照左端点排序,然后我们用平衡树按照右端点为关键字维护已经扫描过去的线段。

    发现要和当前扫描到的线段连边的是平衡树上(dfs)序连续的一段区间。

    考虑这个边怎么连。

    我们只需要在这个区间的右端点处和这个点连上1的边,中间连0边就行了。

    所以我们可以用并查集的思想,只和右端点连边,在维护一个连0边的(set),如果一个点和两边都连上0边就删掉它。

    代码

    #include<bits/stdc++.h>
    #define N 2000009
    using namespace std;
    typedef long long ll;
    const int mod=1e9+7;
    const int inf=1e9;
    int pre[N],nxt[N],head[N],tot;
    int top,st[N];
    int n;
    int vis[N];
    inline ll rd(){
      ll x=0;char c=getchar();bool f=0;
      while(!isdigit(c)){if(c=='-')f=1;c=getchar();}
      while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
      return f?-x:x;
    }
    inline void MOD(int &x){x=x>=mod?x-mod:x;}
    inline ll power(ll x,ll y){
      ll ans=1;
      while(y){
        if(y&1)ans=ans*x%mod;
        x=x*x%mod;y>>=1;
      }
      return ans;
    }
    struct edge{
      int n,to,l;
    }e[N*6];
    inline void add(int u,int v,int l){
      if(!u||!v)return;
     // cout<<u<<" "<<v<<" "<<l<<endl;
      e[++tot].n=head[u];e[tot].to=v;head[u]=tot;e[tot].l=l;
      e[++tot].n=head[v];e[tot].to=u;head[v]=tot;e[tot].l=l;
    }
    struct node{
      int l,r;
      inline bool operator <(const node &b)const{
        if(l!=b.l)return l<b.l;
        return r<b.r;
      }
    }a[N];
    struct nd{
      int pos,id;
      inline bool operator <(const nd &b)const{
        return pos<b.pos;
      }
    };
    set<nd>s1,s2;
    set<nd>::iterator it;
    void dfs(int u){
      for(int i=head[u];i;i=e[i].n){
        int v=e[i].to;
        if(vis[v]&&(vis[u]^e[i].l)!=vis[v]){puts("0");exit(0);}
        if(!vis[v]){
          vis[v]=vis[u]^e[i].l;
          dfs(v);
        }
      }
    }
    int main(){
      n=rd();
      for(int i=1;i<=n;++i)a[i].l=rd(),a[i].r=rd();
      sort(a+1,a+n+1);
      s1.insert(nd{-inf,0});s1.insert(nd{inf,0});
      s2.insert(nd{-inf,0});s2.insert(nd{inf,0});
      for(int i=1;i<=n;++i){
        it=s1.lower_bound(nd{a[i].r,i});
        nxt[i]=it->id;
        pre[it->id]=0;
        it--;
        pre[i]=it->id;
        nxt[it->id]=0;
        if(it->pos>a[i].l)add(i,it->id,1);
        it=s2.lower_bound(nd{a[i].r,i});--it;
        while(1){
          if(it->pos<a[i].l)break;
          if(pre[it->id]&&a[pre[it->id]].r>a[i].l){add(it->id,pre[it->id],0);pre[it->id]=0;}
          if(nxt[it->id]&&a[nxt[it->id]].r<a[i].r){add(it->id,nxt[it->id],0);nxt[it->id]=0;}
          if(!pre[it->id]&&!nxt[it->id])st[++top]=it->id;
          it--;
        }
        for(int j=1;j<=top;++j)s2.erase(nd{a[st[j]].r,st[j]});
        top=0;    
        s1.insert(nd{a[i].r,i});
        s2.insert(nd{a[i].r,i});
      }
      int ans=1;
      for(int i=1;i<=n;++i)if(!vis[i]){
        vis[i]=2;
        dfs(i);
        MOD(ans=ans+ans);
      }
      printf("%d
    ",ans);
      return 0;
    }
    
  • 相关阅读:
    第一阶段冲刺第七天
    第一阶段冲刺第六天
    PHPCMS V9.6.0 SQL注入漏洞分析
    metinfo小于v6.2.0版本SQL盲注利用脚本
    metinfo小于v6.2.0版本通杀SQL盲注漏洞分析
    PHPSHE 1.7前台SQL注入漏洞分析
    sqli-labs Less-1~~~Less-23
    内网渗透靶场测试:(二)hash传递和黄金票据
    内网渗透靶场测试:(一)反向代理,互联互通
    intel:spectre&Meltdown侧信道攻击(五)—— DRAM address mapping
  • 原文地址:https://www.cnblogs.com/ZH-comld/p/11125508.html
Copyright © 2011-2022 走看看