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
  • 相关阅读:
    DW吃瓜课程——机器学习理论知识笔记(四)
    DW吃瓜课程——机器学习理论知识笔记(三)
    DW吃瓜课程——机器学习理论知识笔记(二)
    DW吃瓜课程——机器学习理论知识笔记(一)
    DataWhale编程实践——区块链学习笔记
    CV入门系列笔记——全球人工智能技术创新大赛【热身赛】CV异常检测赛道
    强化学习入门笔记系列——DDPG算法
    强化学习入门笔记系列——稀疏奖赏和模仿学习
    强化学习入门笔记系列——DQN算法
    Java_SPI思想
  • 原文地址:https://www.cnblogs.com/MingSD/p/9510916.html
Copyright © 2011-2022 走看看