傳送門:https://nanti.jisuanke.com/t/41399
題目描述
There are light bulbs indexed from to . Initially, all of them are off.
A operation switches the state of a contiguous subset of bulbs. means to flip all bulbs xx such that . So for example, means to flip bulbs 3 , 4 and 5, and means to flip bulb 5.
Given the value of and a sequence of flips, count the number of light bulbs that will be on at the end state.
輸入格式
The first line of the input gives the number of test cases, T. T test cases follow. Each test case starts with a line containing two integers N and M, the number of light bulbs and the number of operations, respectively. Then, there are M more lines, the ii-th of which contains the two integers and , indicating that the ii-th operation would like to flip all the bulbs from
to , inclusive.
輸出格式
For each test case, output one line containing Case #, where x is the test case number (starting from 1) and y is the number of light bulbs that will be on at the end state, as described above.
樣例輸入
2
10 2
2 6
4 8
6 3
1 1
2 3
3 4
樣例輸出
Case #1: 4
Case #2: 3
① 線段樹做法(MLE)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e6 + 10;
int t, n, m, x, y;
struct node { int l, r, sum, flip; } tree[maxn << 2];
inline const int read()
{
int x = 0, f = 1; char ch = getchar();
while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9') { x = (x << 3) + (x << 1) + ch - '0'; ch = getchar(); }
return x * f;
}
inline int ls(int id) { return id << 1; }
inline int rs(int id) { return id << 1 | 1; }
void push_up(int id)
{
tree[id].sum = tree[ls(id)].sum + tree[rs(id)].sum;
}
void push_down(int id)
{
if (tree[id].flip)
{
tree[ls(id)].flip ^= 1; tree[rs(id)].flip ^= 1;
tree[ls(id)].sum = tree[ls(id)].r - tree[ls(id)].l + 1 - tree[ls(id)].sum;
tree[rs(id)].sum = tree[rs(id)].r - tree[rs(id)].l + 1 - tree[rs(id)].sum;
tree[id].flip = 0;
}
}
void build(int id, int l, int r)
{
tree[id].l = l; tree[id].r = r;
tree[id].sum = tree[id].flip = 0;
if (l == r) return;
int mid = (l + r) >> 1;
build(ls(id), l, mid);
build(rs(id), mid + 1, r);
push_up(id);
}
void update(int id, int l, int r)
{
if (tree[id].l == l && tree[id].r == r)
{
tree[id].flip ^= 1;
tree[id].sum = r - l + 1 - tree[id].sum;
return;
}
push_down(id);
int mid = (tree[id].l + tree[id].r) >> 1;
if (r <= mid) update(ls(id), l, r);
else if (l > mid) update(rs(id), l, r);
else
{
update(ls(id), l, mid);
update(rs(id), mid + 1, r);
}
push_up(id);
}
int query(int id, int l, int r)
{
if (tree[id].l == l && tree[id].r == r) return tree[id].sum;
push_down(id);
int mid = (tree[id].l + tree[id].r) >> 1;
if (r <= mid) return query(ls(id), l, r);
if (l > mid) return query(rs(id), l, r);
return query(ls(id), l, mid) + query(rs(id), mid + 1, r);
}
int main()
{
t = read();
for (int i = 1; i <= t; i++)
{
printf("Case #%d: ", i);
n = read(); m = read();
build(1, 1, n);
while (m--)
{
x = read() + 1; y = read() + 1;
update(1, x, y);
}
printf("%d\n", query(1, 1, n));
}
return 0;
}
②
對於每一對Li、Ri,我們將其定義爲:將Li之前的所有燈全都filp一次,再將Ri之前的所有燈全都filp一次,如圖,即爲將C段先翻轉一次,再將A段翻轉一次,這樣一來,C段的燈被翻轉了2次,即沒有變化,而B段則被翻轉了1次,達成了翻轉[Li, Ri]區間的效果。
故,我們將所有的 Li(1 ~ Li-1)和 Ri+1(要包括Ri,故爲Ri+1之前)保存在一個數組中,再將其由小到大排序遍歷,維護在此座標之前亮着的燈的數量(翻轉一次即爲 )
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e6 + 10;
int v[maxn];
inline const int read()
{
int x = 0, f = 1; char ch = getchar();
while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9') { x = (x << 3) + (x << 1) + ch - '0'; ch = getchar(); }
return x * f;
}
int main()
{
int t = read();
for (int i = 1; i <= t; i++)
{
int n = read(), m = read(), cnt = 0, ans = 0;
while (m--)
{
v[cnt++] = read();
v[cnt++] = read() + 1;
}
sort(v, v + cnt);
for (int j = 0; j < cnt; j++) ans = v[j] - ans;
printf("Case #%d: %d\n", i, ans);
}
return 0;
}