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 }

因为一直在实验室问步骤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 }

原文地址:https://www.cnblogs.com/MingSD/p/9510916.html

时间: 2024-10-23 15:53:08

CodeForces gym Nasta Rabbara lct的相关文章

Codeforces gym Hello 2015 Div1 B and Div2 D

Codeforces gym 100571 problem D Problem 给一个有向图G<V,E>和源点S,边的属性有长度L和颜色C,即E=<L,C>.进行Q次询问,每次给定一个点X,输出S到X的最短路的长度(不存在则输出 -1).但要求S到X的路径中相邻两条边颜色不一样. Limits Time Limit(ms): 1000 Memory Limit(MB): 256 |V|, |E|: [1, 10^5] X, S: [1, |V| ] L: [1, 10^9] |C|

Codeforces gym Hello 2015 Div1 E

Codeforces gym 100570 problem E (一种处理动态最长回文子串问题的方法) Problem 给一个长度为N的字符串S,字符集是'a'-'z'.进行Q次操作,操作分三种.一,修改位置X的字符为C:二,查询以P位置为中心的最长回文子串的长度,并输出:三,查询以P与P+1的中间位置为中心的最长回文子串的长度,并输出. More 第二种操作子串长度为奇数,一定存在:第三种操作子串长度为偶数,若不存在,输出 -1. Limits Time Limit(ms): 4000(1s足

Codeforces gym Hello 2015 Div1 C and Div2 E

Codeforces gym 100570 problem C Codeforces gym 100571 problem E Problem 给一个N行M列的矩阵Ma,进行Q次(Q<=10)查询,每次给定一个K,问有多少子矩阵,满足最大值max - 最小值min <=K. Limits Time Limit(ms): 8000 Memory Limit(MB): 512 N, M: [1, 400] Q: [1, 10] Ma(i, j), K: [1, 10^9] Solution (Th

【模拟】ECNA 2015 I What&#39;s on the Grille? (Codeforces GYM 100825)

题目链接: http://codeforces.com/gym/100825 题目大意: 栅栏密码.给定N(N<=10),密钥为一个N*N的矩阵,'.'代表空格可以看到,'X'代表被遮挡,还有密文字符串S,长度为N*N 每次将这个矩阵顺时针旋转90°,把矩阵中空格对应的位置按照从上到下从左到右的顺序依次填充上密文字符,求最终这个密文字符能否填满N*N的矩阵,能按顺序输出得到的答案,不能输出"invalid grille" 题目思路: [模拟] 直接模拟即可.旋转的坐标公式很好推.

Codeforces gym Hello 2015 Div2 B

Codeforces gym 100571 problem B Problem 设函数F(x),F(1)与F(2)已知,且当 i>=3,F(i)=a*F(i-2)+b*F(i-1).再给一个长度为N的数列A,进行Q次如下操作:每次给一个区间[L, R],对于每个k(L=<k<=R),将A[k]=A[k]+F[k-L+1].最后输出数列A(mod 10^9+7). Limits Time Limit(ms): 1000 Memory Limit(MB): 256 N, Q: [1, 10^

Codeforces Gym - 101147J Whistle&#39;s New Car

Discription Statements Whistle has bought a new car, which has an infinite fuel tank capacity. He discovered an irregular country since it has n cities and there are exactly n?-?1roads between them, of course, all cities are connected. He is so much

Codeforces Gym 101174 A Within Arm&#39;s Reach 贪心 手臂

#include<iostream> #include<stdio.h> #include <string.h> #include <algorithm> #include <vector> #include <math.h> using namespace std; #define LL long long const int maxn=25; double a[maxn],l[maxn],r[maxn]; double ex,ey

[Codeforces 603E]Pastoral Oddities(LCT)

[Codeforces 603E]Pastoral Oddities(LCT) 题面 图中有n个孤立点,依次向图中加入m条带权无向边.使得图中每个点的度数均为奇数的边集是合法的,其权值定义为集合中的最大边权.每次加入边后,询问权值最小的合法边集的权值,不存在合法边集时输出?1. \(n \leq 10^5,m \leq 3\times 10^5\) 分析 手玩样例可得:图存在合法边集,当且仅当每个连通块的大小为偶数 证明: 先证明充分性:假设某合法连通块大小为奇数,那么该块的总度数是奇数.但所有

Codeforces Gym 100269 Dwarf Tower (最短路)

题目连接: http://codeforces.com/gym/100269/attachments Description Little Vasya is playing a new game named "Dwarf Tower". In this game there are n different items,which you can put on your dwarf character. Items are numbered from 1 to n. Vasya want