CF981E. Addition on Segments
\(\texttt{Difficulty:2200}\)
题意
一个长为 \(n(1\le n\le 10000)\) 的序列,一开始都为 \(0\) ,有 \(q(1\le q\le10000)\) 次操作,每次操作将区间 \([l,r]\) 的所有数加上 \(x(1\le x\le n)\) 。求存在哪些 \(k(1\le k\le n)\) ,使得从中选出若干次操作执行后,序列中的最大值恰好为 \(k\) 。
题解
考虑最大值出现的位置,如果位置 \(i\) 上的数作为最大值,那么只要仅选择包含了位置 \(i\) 的区间即可,我们可以用 \(\texttt{bitset}\) 来对每个位置求出能够得到的最大值集合,发现如果直接维护的话,在过程中需要撤销一些操作,考虑用线段树分治来解决,将所有操作和询问标记到线段树上,之后遍历一遍线段树,每个节点维护 \(\texttt{bitset}\) 表示从该位置到根所累积的贡献,在叶节点处统计答案即可,此外主要 \(\texttt{bitset}\) 初始为 \(1\) ,复杂度 \(\mathcal{O}(\frac{nq\log n}{\omega})\) 。
代码
View Code
#include<bits/stdc++.h>
#include<unordered_map>
#include<unordered_set>
using namespace std;
using LL = long long;
using LD = long double;
using ULL = unsigned long long;
using PII = pair<int, int>;
using TP = tuple<int, int, int>;
#define all(x) x.begin(),x.end()
#define mst(x,v) memset(x,v,sizeof(x))
#define mul(x,y) (1ll*(x)*(y)%mod)
#define mk make_pair
//#define int LL
//#define double LD
#define lc p*2
#define rc p*2+1
#define endl '\n'
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
#pragma warning(disable : 4996)
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
const double eps = 1e-10;
const double pi = acos(-1);
const LL MOD = 1000000007;
const LL mod = 998244353;
const int maxn = 10010;
struct Node {
int l, r;
bitset<maxn>f;
vector<int>dat;
}tr[maxn * 4];
bitset<maxn>ans;
void build(int p, int l, int r)
{
tr[p].l = l, tr[p].r = r, tr[p].f |= 1;
if (l + 1 == r)
return;
int mid = (l + r) >> 1;
build(lc, l, mid), build(rc, mid, r);
}
void modify(int p, int l, int r, int x)
{
if (tr[p].l >= l && tr[p].r <= r)
{
tr[p].dat.push_back(x);
return;
}
int mid = (tr[p].l + tr[p].r) >> 1;
if (l < mid)
modify(lc, l, r, x);
if (r > mid)
modify(rc, l, r, x);
}
void calc(int p)
{
for (auto& x : tr[p].dat)
tr[p].f |= (tr[p].f << x);
if (tr[p].l + 1 == tr[p].r)
{
ans |= tr[p].f;
return;
}
tr[lc].f = tr[rc].f = tr[p].f;
calc(lc), calc(rc);
}
int N, Q;
void solve()
{
build(1, 1, N + 1);
int l, r, x;
while (Q--)
{
cin >> l >> r >> x;
modify(1, l, r + 1, x);
}
calc(1);
vector<int>k;
for (int i = 1; i <= N; i++)
{
if (ans.test(i))
k.push_back(i);
}
cout << k.size() << endl;
for (auto& x : k)
cout << x << ' ';
cout << endl;
}
int main()
{
IOS;
cin >> N >> Q;
solve();
return 0;
}