zoukankan      html  css  js  c++  java
  • CodeForces gym Nasta Rabbara lct

    Nasta Rabbara

    题意:简单来说就是, 现在有 n个点, m条边, 每次询问一个区间[ l ,  r ], 将这个区间的所有边都连上, 如果现在的图中有奇数环, 就输出 “Impossible”, 否者就输出 ”possible“。

    题解:

    步骤1:我们先找出每个最小的 [ l,  r]  当这个区间的边都出现后, 就会出现一个奇数环。

    步骤2:问题就变成了对于一次询问 [ L, R ]  是否存在上面的一个区间 被完全覆盖。

    对于步骤1来说:需要加边和删边, 我们用 lct 维护。

    我们按照 1 ... m 的顺序, 进行添加边。

    如果 u 和 v 不联通, 那么我们直接将u和v连起来。

    如果 u 和 v 联通, 那么如果我们加上这个边之后就会形成环。

    如果是偶数环, 那么我们就删除这个环上最先添加进来的边, 因为我们需要找到最小的[l, r]奇数环区间。

    如果是奇数环, 那么说明我们已经找到了一个奇数环区间, 因为有偶数环删除的保证, 所以我们找到的一定是最小的奇数环区间。

    然后我们再删除边,将 l+1前面的边都删除, 继续往下找下一个最小奇数环区间。

    对于步骤2来说:

    我们可以离线所有询问。

    对于所有的最小奇数环区间和询问区间都按照左端点大的排序。

    当询问区间的 左端点的位置 <= 当前奇数环区间的时候,就在标记一下奇数环区间的右端, 用树状数组维护。

    然后查询询问区间的右端点之前有没有点出现过, 如果有就说明有区间被完全覆盖。

    因为添加到树状数组里面的 奇数环区间 的左端点一定是 大或等于 当前区间左端点的。

    最后输出答案。

    代码:

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define Fopen freopen("2.in","r",stdin); freopen("_out.txt","w",stdout);
      4 #define LL long long
      5 #define ULL unsigned LL
      6 #define fi first
      7 #define se second
      8 #define pb push_back
      9 #define lson l,m,rt<<1
     10 #define rson m+1,r,rt<<1|1
     11 #define lch(x) tr[x].son[0]
     12 #define rch(x) tr[x].son[1]
     13 #define max3(a,b,c) max(a,max(b,c))
     14 #define min3(a,b,c) min(a,min(b,c))
     15 typedef pair<int,int> pll;
     16 const int inf = 0x3f3f3f3f;
     17 const LL INF = 0x3f3f3f3f3f3f3f3f;
     18 const LL mod =  (int)1e9+7;
     19 const int N = 2e5 + 100;
     20 struct Node{
     21     int rev, rt;
     22     int son[2], pre;
     23     int id, mn, sz;
     24     void init(int t){
     25         sz = rt = 1;
     26         rev = pre = son[0] = son[1] = 0;
     27         id = mn = t;
     28     }
     29 }tr[N];
     30 void Push_Rev(int x){
     31     if(!x) return ;
     32     swap(lch(x), rch(x));
     33     tr[x].rev ^= 1;
     34 }
     35 void Push_Up(int x){
     36     if(!x) return ;
     37     tr[x].sz = tr[lch(x)].sz + tr[rch(x)].sz + 1;
     38     tr[x].mn = min3(tr[lch(x)].mn, tr[rch(x)].mn, tr[x].id);
     39 }
     40 void Push_Down(int x){
     41    if(tr[x].rev){
     42         tr[x].rev = 0;
     43         Push_Rev(lch(x));
     44         Push_Rev(rch(x));
     45     }
     46 }
     47 void Rev(int x){
     48     if(!tr[x].rt) Rev(tr[x].pre);
     49     Push_Down(x);
     50 }
     51 void rotate(int x){
     52     if(tr[x].rt) return;
     53     int y = tr[x].pre, z = tr[y].pre;
     54     int k = (rch(y) == x);
     55     tr[y].son[k] = tr[x].son[k^1];
     56     tr[tr[y].son[k]].pre = y;
     57     tr[x].son[k^1] = y;
     58     tr[y].pre = x;
     59     tr[x].pre = z;
     60     if(tr[y].rt) tr[y].rt = 0, tr[x].rt = 1;
     61     else tr[z].son[rch(z) == y] = x;
     62     Push_Up(y);
     63 }
     64 void Splay(int x){
     65      Rev(x);
     66      while(!tr[x].rt){
     67         int y = tr[x].pre, z = tr[y].pre;
     68         if(!tr[y].rt){
     69             if(( x == rch(y) ) != (y == rch(z))) rotate(y);
     70             else rotate(x);
     71         }
     72         rotate(x);
     73     }
     74     Push_Up(x);
     75 }
     76 void Access(int x){
     77     int y = 0;
     78     do{
     79         Splay(x);
     80         tr[rch(x)].rt = 1;
     81         rch(x) = y;
     82         tr[y].rt = 0;
     83         Push_Up(x);
     84         y = x;
     85         x = tr[x].pre;
     86     }while(x);
     87 }
     88 void Make_rt(int x){
     89     Access(x);
     90     Splay(x);
     91     Push_Rev(x);
     92 }
     93 void link(int u, int v){
     94     Make_rt(u);
     95     tr[u].pre = v;
     96 }
     97 void cut(int u, int v){
     98     Make_rt(u);
     99     Access(v);
    100     Splay(v);
    101     tr[lch(v)].pre = 0;
    102     tr[lch(v)].rt = 1;
    103     tr[v].pre = 0;
    104     lch(v) = 0;
    105 }
    106 bool judge(int u, int v){
    107     while(tr[u].pre) u = tr[u].pre;
    108     while(tr[v].pre) v = tr[v].pre;
    109     return u == v;
    110 }
    111 int x[N], y[N];
    112 int l[N], r[N];
    113 int in[N];
    114 int ans[N];
    115 int tot = 0;
    116 int n, m, q;
    117 struct node{
    118     int l, r, id;
    119     bool operator < (const node & x) const {
    120         return l > x.l;
    121     }
    122 }A[N];
    123 void solve(int st, int ed){
    124     for(int i = st; i <= ed; i++){
    125         if(!in[i]) continue;
    126         cut(x[i], i+n);
    127         cut(y[i], i+n);
    128         in[i] = 0;
    129     }
    130 }
    131 int tree[N];
    132 inline int lowbit(int x){
    133     return x & (-x);
    134 }
    135 int Query(int x){
    136     int ret = 0;
    137     while(x){
    138         ret += tree[x];
    139         x -= lowbit(x);
    140     }
    141     return ret;
    142 }
    143 void Add(int x){
    144     while(x <= m){
    145         tree[x]++;
    146         x += lowbit(x);
    147     }
    148 }
    149 int main(){
    150     scanf("%d%d%d", &n, &m, &q);
    151     for(int i = 1; i <= n; i++) tr[i].init(inf);
    152     tr[0].mn = tr[0].id = inf;
    153     for(int i = 1; i <= m; i++){
    154         scanf("%d%d", &x[i], &y[i]);
    155         tr[i+n].init(i+n);
    156     }
    157     int b = 1;
    158     for(int i = 1; i <= m; i++){
    159         int u = x[i], v = y[i], id = n+i;
    160         if(!judge(u, v)){
    161             link(u, id);
    162             link(v, id);
    163             in[i] = 1;
    164         }
    165         else {
    166             Make_rt(u);
    167             Access(v);
    168             Splay(v);
    169             int sz = tr[v].sz/2;
    170             int t = tr[v].mn;
    171             if(sz&1) {
    172                 cut(u, t);
    173                 cut(v, t);
    174                 in[t-n] = 0;
    175             }
    176             else {
    177                 l[++tot] = t-n; r[tot] = i;
    178                 solve(b, t-n);
    179                 b = t-n;
    180             }
    181             link(u, id);
    182             link(v, id);
    183             in[i] = 1;
    184         }
    185     }
    186     for(int i = 1; i <= q; i++){
    187         scanf("%d%d", &A[i].l, &A[i].r);
    188         A[i].id = i;
    189     }
    190     sort(A+1, A+1+q);
    191     for(int i = 1; i <= q; i++){
    192         int ll = A[i].l, rr = A[i].r, id = A[i].id;
    193         while(tot && ll <= l[tot]){
    194             Add(r[tot]);
    195             tot--;
    196         }
    197         if(Query(rr)) ans[id] = 1;
    198     }
    199     for(int i = 1; i <= q; i++){
    200         if(ans[i]) puts("Impossible");
    201         else puts("Possible");
    202     }
    203     return 0;
    204 }
    View Code

    因为一直在实验室问步骤2的问题, 又听到一个别的思路。

    因为我们保证了最小奇数环区间是没有覆盖情况的, 我们按照左端点小的排序。

    对于每次询问我们找到第一段左端点大于询问区间的左端点的区间, 然后判断一下右端点是不是在这个区间里面就好了。

    代码:

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define Fopen freopen("2.in","r",stdin); freopen("_out.txt","w",stdout);
      4 #define LL long long
      5 #define ULL unsigned LL
      6 #define fi first
      7 #define se second
      8 #define pb push_back
      9 #define lson l,m,rt<<1
     10 #define rson m+1,r,rt<<1|1
     11 #define lch(x) tr[x].son[0]
     12 #define rch(x) tr[x].son[1]
     13 #define max3(a,b,c) max(a,max(b,c))
     14 #define min3(a,b,c) min(a,min(b,c))
     15 typedef pair<int,int> pll;
     16 const int inf = 0x3f3f3f3f;
     17 const LL INF = 0x3f3f3f3f3f3f3f3f;
     18 const LL mod =  (int)1e9+7;
     19 const int N = 2e5 + 100;
     20 struct Node{
     21     int rev, rt;
     22     int son[2], pre;
     23     int id, mn, sz;
     24     void init(int t){
     25         sz = rt = 1;
     26         rev = pre = son[0] = son[1] = 0;
     27         id = mn = t;
     28     }
     29 }tr[N];
     30 void Push_Rev(int x){
     31     if(!x) return ;
     32     swap(lch(x), rch(x));
     33     tr[x].rev ^= 1;
     34 }
     35 void Push_Up(int x){
     36     if(!x) return ;
     37     tr[x].sz = tr[lch(x)].sz + tr[rch(x)].sz + 1;
     38     tr[x].mn = min3(tr[lch(x)].mn, tr[rch(x)].mn, tr[x].id);
     39 }
     40 void Push_Down(int x){
     41    if(tr[x].rev){
     42         tr[x].rev = 0;
     43         Push_Rev(lch(x));
     44         Push_Rev(rch(x));
     45     }
     46 }
     47 void Rev(int x){
     48     if(!tr[x].rt) Rev(tr[x].pre);
     49     Push_Down(x);
     50 }
     51 void rotate(int x){
     52     if(tr[x].rt) return;
     53     int y = tr[x].pre, z = tr[y].pre;
     54     int k = (rch(y) == x);
     55     tr[y].son[k] = tr[x].son[k^1];
     56     tr[tr[y].son[k]].pre = y;
     57     tr[x].son[k^1] = y;
     58     tr[y].pre = x;
     59     tr[x].pre = z;
     60     if(tr[y].rt) tr[y].rt = 0, tr[x].rt = 1;
     61     else tr[z].son[rch(z) == y] = x;
     62     Push_Up(y);
     63 }
     64 void Splay(int x){
     65      Rev(x);
     66      while(!tr[x].rt){
     67         int y = tr[x].pre, z = tr[y].pre;
     68         if(!tr[y].rt){
     69             if(( x == rch(y) ) != (y == rch(z))) rotate(y);
     70             else rotate(x);
     71         }
     72         rotate(x);
     73     }
     74     Push_Up(x);
     75 }
     76 void Access(int x){
     77     int y = 0;
     78     do{
     79         Splay(x);
     80         tr[rch(x)].rt = 1;
     81         rch(x) = y;
     82         tr[y].rt = 0;
     83         Push_Up(x);
     84         y = x;
     85         x = tr[x].pre;
     86     }while(x);
     87 }
     88 void Make_rt(int x){
     89     Access(x);
     90     Splay(x);
     91     Push_Rev(x);
     92 }
     93 void link(int u, int v){
     94     Make_rt(u);
     95     tr[u].pre = v;
     96 }
     97 void cut(int u, int v){
     98     Make_rt(u);
     99     Access(v);
    100     Splay(v);
    101     tr[lch(v)].pre = 0;
    102     tr[lch(v)].rt = 1;
    103     tr[v].pre = 0;
    104     lch(v) = 0;
    105 }
    106 bool judge(int u, int v){
    107     while(tr[u].pre) u = tr[u].pre;
    108     while(tr[v].pre) v = tr[v].pre;
    109     return u == v;
    110 }
    111 int x[N], y[N];
    112 int in[N];
    113 int ans[N];
    114 int tot = 0;
    115 pll P[N];
    116 int n, m, q;
    117 void solve(int st, int ed){
    118     for(int i = st; i <= ed; i++){
    119         if(!in[i]) continue;
    120         cut(x[i], i+n);
    121         cut(y[i], i+n);
    122         in[i] = 0;
    123     }
    124 }
    125 int main(){
    126     scanf("%d%d%d", &n, &m, &q);
    127     for(int i = 1; i <= n; i++) tr[i].init(inf);
    128     tr[0].mn = tr[0].id = inf;
    129     for(int i = 1; i <= m; i++){
    130         scanf("%d%d", &x[i], &y[i]);
    131         tr[i+n].init(i+n);
    132     }
    133     int b = 1;
    134     for(int i = 1; i <= m; i++){
    135         int u = x[i], v = y[i], id = n+i;
    136         if(!judge(u, v)){
    137             link(u, id);
    138             link(v, id);
    139             in[i] = 1;
    140         }
    141         else {
    142             Make_rt(u);
    143             Access(v);
    144             Splay(v);
    145             int sz = tr[v].sz/2;
    146             int t = tr[v].mn;
    147             if(sz&1) {
    148                 cut(u, t);
    149                 cut(v, t);
    150                 in[t-n] = 0;
    151             }
    152             else {
    153                 P[tot].fi = t-n; P[tot++].se = i;
    154 
    155                 solve(b, t-n);
    156                 b = t-n;
    157             }
    158             link(u, id);
    159             link(v, id);
    160             in[i] = 1;
    161         }
    162     }
    163     int l, r;
    164     for(int i = 1; i <= q; i++){
    165         scanf("%d%d", &l, &r);
    166         int p = upper_bound(P, P+tot, pll(l,-1)) - P;
    167         if(p == tot || r < P[p].se) puts("Possible");
    168         else puts("Impossible");
    169     }
    170     return 0;
    171 }
    View Code
  • 相关阅读:
    @RequestParam注解使用:Name for argument type [java.lang.String] not available, and parameter name information not found in class file either.
    cglib动态代理导致注解丢失问题及如何修改注解允许被继承
    springboot Autowired BeanNotOfRequiredTypeException
    git根据用户过滤提交记录
    不同包下,相同数据结构的两个类进行转换
    How to use Jackson to deserialise an array of objects
    jooq实践
    java如何寻找main函数对应的类
    Python--matplotlib
    Python 和 Scikit-Learn
  • 原文地址:https://www.cnblogs.com/MingSD/p/9510916.html
Copyright © 2011-2022 走看看