1.题意
小 A 和小 B 在玩一个游戏。
首先,小 A 写了一个由 0 和 1 组成的序列 S,长度为 N。
然后,小 B 向小 A 提出了 M 个问题。
在每个问题中,小 B 指定两个数 l 和 r,小 A 回答 S[l∼r] 中有奇数个 1 还是偶数个 1。
机智的小 B 发现小 A 有可能在撒谎。
例如,小 A 曾经回答过 S[1∼3] 中有奇数个 1,S[4∼6] 中有偶数个 1,现在又回答 S[1∼6] 中有偶数个 1,显然这是自相矛盾的。
请你帮助小 B 检查这 M 个答案,并指出在至少多少个回答之后可以确定小 A 一定在撒谎。
即求出一个最小的 k,使得 01 序列 S 满足第 1∼k 个回答,但不满足第 1∼k+1 个回答。
输入格式
第一行包含一个整数 N,表示 01 序列长度。
第二行包含一个整数 M,表示问题数量。
接下来 M 行,每行包含一组问答:两个整数 l 和 r,以及回答 even 或 odd,用以描述 S[l∼r] 中有偶数个 1 还是奇数个 1。
输出格式
输出一个整数 k,表示 01 序列满足第 1∼k 个回答,但不满足第 1∼k+1 个回答,如果 01 序列满足所有回答,则输出问题总数量。
数据范围
N≤109,M≤10000
2.分析
维护从前缀和’1’个数的奇偶性。
如果[l,r]有奇数个1,等价于pre[l-1]!=pre[r].
等价于(l-1),( r )'在一个并查集块,(l-1)‘,( r )在一个并查集块。
同理如果[l,r]有偶数个1,等价于pre[l-1]==pre[r].
转化完之后就可以o(n)求解。
3.并查集代码
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <sstream>
#include <cstdio>
#include <vector>
#include <string>
#include <cmath>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <ctime>
using namespace std;
//-----pre_def----
const double PI = acos(-1.0);
const int INF = 0x3f3f3f3f;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
#define fir(i, a, b) for (int i = (a); i <= (b); i++)
#define rif(i, a, b) for (int i = (a); i >= (b); i--)
#define endl '\n'
#define init_h memset(h, -1, sizeof h), idx = 0;
#define lowbit(x) x &(-x)
//---------------
const int N = 2000010;
vector<int> lsh;
int cnt = 0, n, m;
int f[N], l[N], r[N], op[N];
void init()
{
fir(i, 0, N) f[i] = i;
}
int find(int x)
{
if (f[x] != x)
{
f[x] = find(f[x]);
}
return f[x];
}
void modify(int x, int y)
{
int pa = find(x);
int pb = find(y);
if (pa != pb)
f[pa] = pb;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
int StartTime = clock();
#endif
scanf("%d%d", &n, &m);
init();
fir(i, 1, m)
{
char tmp[10];
scanf("%d%d%s", &l[i], &r[i], tmp);
l[i]--;
op[i] = (tmp[0] == 'o');
lsh.push_back(l[i]);
lsh.push_back(r[i]);
}
sort(lsh.begin(), lsh.end());
lsh.erase(unique(lsh.begin(), lsh.end()), lsh.end());
fir(i, 1, m) //lsh
{
l[i] = lower_bound(lsh.begin(), lsh.end(), l[i]) - lsh.begin();
r[i] = lower_bound(lsh.begin(), lsh.end(), r[i]) - lsh.begin();
}
fir(i, 1, m)
{
if (op[i])
{
f[find(l[i])] = find(r[i] + lsh.size());
f[find(r[i])] = find(l[i] + lsh.size());
}
else
{
f[find(l[i])] = find(r[i]);
f[find(r[i] + lsh.size())] = find(l[i] + lsh.size());
}
if (find(r[i]) == find(r[i] + lsh.size()) || find(l[i]) == find(l[i] + lsh.size()))
{
printf("%d", i - 1);
return 0;
}
}
printf("%d", m);
#ifndef ONLINE_JUDGE
printf("Run_Time = %d ms\n", clock() - StartTime);
#endif
return 0;
}
4.2-SAT
这题令人很想二分套一个2-SAT,,
如果用前k个关系建完图之后,如果x与x’在一个scc中则非法。
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <sstream>
#include <cstdio>
#include <vector>
#include <string>
#include <cmath>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <ctime>
using namespace std;
//-----pre_def----
const double PI = acos(-1.0);
const int INF = 0x3f3f3f3f;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
#define fir(i, a, b) for (int i = (a); i <= (b); i++)
#define rif(i, a, b) for (int i = (a); i >= (b); i--)
#define endl '\n'
#define init_h memset(h, -1, sizeof h), idx = 0;
#define lowbit(x) x &(-x)
//---------------
const int N = 2000010, M = 1e4 + 10;
vector<int> lsh;
int cnt = 0, n, m;
int f[N], l[N], r[N], op[N], len;
int h[M << 1], e[M << 2], ne[M << 2], idx;
bool in_stack[N];
int out[N];
int color[N], stk[N], top, dfn[N], low[N], times, sizes[N], scc_cnt;
void init()
{
init_h;
times = 0;
memset(dfn, 0, sizeof dfn);
scc_cnt = 0;
}
void add(int a, int b)
{
e[idx] = b;
ne[idx] = h[a];
h[a] = idx++;
e[idx] = a;
ne[idx] = h[b];
h[b] = idx++;
}
void tarjan(int u)
{
dfn[u] = low[u] = ++times;
stk[++top] = u, in_stack[u] = true;
for (int i = h[u]; ~i; i = ne[i])
{
int j = e[i];
if (!dfn[j])
{
tarjan(j);
low[u] = min(low[u], low[j]);
}
else if (in_stack[j])
{
low[u] = min(low[u], dfn[j]);
}
}
if (dfn[u] == low[u])
{
++scc_cnt;
int y;
do
{
y = stk[top--];
in_stack[y] = false;
color[y] = scc_cnt;
sizes[scc_cnt]++;
} while (y != u);
}
}
bool check(int x)
{
init();
//cout << x << ":" << endl;
fir(i, 1, x)
{
if (op[i])
{
add(l[i], r[i] + len);
add(r[i], l[i] + len);
}
else
{
add(l[i], r[i]);
add(r[i] + len, l[i] + len);
}
}
for (int i = 1; i <= len; i++)
if (!dfn[i])
tarjan(i);
for (int i = 1; i <= len; i++)
{
//cout << color[i] << endl;
if (color[i] == color[i + len])
return 0;
}
return 1;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
int StartTime = clock();
#endif
scanf("%d%d", &n, &m);
init();
fir(i, 1, m)
{
char tmp[10];
scanf("%d%d%s", &l[i], &r[i], tmp);
l[i]--;
op[i] = (tmp[0] == 'o');
lsh.push_back(l[i]);
lsh.push_back(r[i]);
}
sort(lsh.begin(), lsh.end());
lsh.erase(unique(lsh.begin(), lsh.end()), lsh.end());
len = lsh.size();
fir(i, 1, m) //lsh
{
l[i] = lower_bound(lsh.begin(), lsh.end(), l[i]) - lsh.begin() + 1;
r[i] = lower_bound(lsh.begin(), lsh.end(), r[i]) - lsh.begin() + 1;
}
int l = 0, r = m;
int ans = m;
while (l <= r)
{
int mid = l + r >> 1;
if (check(mid))
{
ans = mid;
l = mid + 1;
}
else
r = mid - 1;
}
cout << ans << endl;
#ifndef ONLINE_JUDGE
printf("Run_Time = %d ms\n", clock() - StartTime);
#endif
return 0;
}