P6684 [BalticOI 2020 Day1] 小丑 题解
不难发现对于一个特定的
所以就可以很自然的想到二分。
由于需要对所有的
只用普通的二分复杂度会炸掉,所以就可以想到使用整体二分。
思路#
首先考虑如何判断奇环。
对于这部分内容,可以考虑一边加边,一边判断奇环。
使用可撤销并查集维护。
如果此时加的边在同一连通块内,直接判断奇偶。
若不在同一个连通块则合并两个连通块,更新奇偶。
至于整体二分的内容可以直接套板子了。
Code#
#include <bits/stdc++.h>
using namespace std;
const int N = 200010;
int n , m , q , top , ans , fa[N] , dep[N] , val[N] , siz[N] , stk[N] , sum[N];
pair<int , int> e[N];
#define fir first
#define sec second
void solve(int l , int r , int L , int R);
inline int read()
{
int asd = 0 , qwe = 1; char zxc;
while(!isdigit(zxc = getchar())) if(zxc == '-') qwe = -1;
while(isdigit(zxc)) asd = asd * 10 + zxc - '0' , zxc = getchar();
return asd * qwe;
}
inline int gf(int x)
{
if(x == fa[x])
return x;
int rt = gf(fa[x]);
dep[x] = dep[fa[x]] ^ val[x];
return rt;
}
inline void calc(int x , int y)
{
if(!x) return;
int fx = gf(x) , fy = gf(y);
if(fx == fy)
return ans |= (dep[x] == dep[y]) , void();
bool flag = (dep[x] == dep[y]);
x = fx , y = fy;
if(siz[x] < siz[y]) swap(x , y);
fa[y] = x , val[y] = flag;
siz[x] += siz[y] , stk[++top] = y;
}
inline void del(int x)
{
while(top > x)
{
int y = stk[top--];
siz[fa[y]] -= siz[y];
fa[y] = y , val[y] = dep[y] = 0;
}
}
inline void cl()
{
ans = top = 0;
for(int i = 1;i <= n;i++)
fa[i] = i , dep[i] = val[i] = 0 , siz[i] = 1;
}
int main()
{
n = read() , m = read() , q = read() , cl();
for(int i = 1;i <= m;i++)
{
e[i].fir = read() , e[i].sec = read();
}
int x = 0;
for(int i = 1;i <= m;i++)
{
calc(e[i].fir , e[i].sec);
if(ans)
{
for(int j = i;j <= m;j++)
sum[j] = m + 1;
x = i;
break;
}
}
if(!ans)
{
while(q--) puts("NO");
return 0;
}
cl();
solve(0 , x - 1 , 1 , m + 1);
for(int i = 1;i <= q;i++)
{
int l = read() , r = read();
puts(sum[l - 1] <= r ? "NO" : "YES");
}
return 0;
}
inline void solve(int l , int r , int L , int R)
{
if(L + 1 == R || l > r)
{
for(int i = l;i <= r;i++)
sum[i] = L;
return;
}
int mid = (L + R) / 2 , ltop = top , lans = ans;
for(int i = R - 1;i >= mid && !ans;i--)
calc(e[i].fir , e[i].sec);
int topl = top , ansl = ans , lmid = min(r , mid - 1);
for(int i = l;i <= lmid;i++)
{
calc(e[i].fir , e[i].sec);
if(ans)
{
lmid = i - 1;
break;
}
}
ans = ansl , del(topl);
solve(l , lmid , L , mid);
ans = lans , del(ltop);
for(int i = l;i <= lmid;i++)
calc(e[i].fir , e[i].sec);
solve(lmid + 1 , r , mid , R);
ans = lans , del(ltop);
}
作者:JiaY19
出处:https://www.cnblogs.com/JiaY19/p/16287228.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)