题目链接:http://codeforces.com/contest/981/problem/E
线段树维护每个询问,然后统计每个区间中出现了多少个点,一边下放标记一边做01背包即可,当然,一看数据是1e4就知道这题不简单,bitset了解一下
代码:
#include<bits/stdc++.h>
#define pb push_back
using namespace std;
const int MAXN=1e4+5;
typedef bitset<MAXN> state;
struct seg
{
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
vector<int> E[MAXN<<2];
void update(int L,int R,int val,int l,int r,int rt)
{
if(L<=l&&r<=R)
{
E[rt].pb(val);
return ;
}
int mid=(l+r)>>1;
if(L<=mid) update(L,R,val,lson);
if(mid<R) update(L,R,val,rson);
}
}se;
state book[MAXN<<2],cur,ans;
void dfs(int l,int r,int now)
{
book[now]=cur;
for(auto i:se.E[now]) cur|=(cur<<i);
ans|=cur;
if(l==r) return ;
int mid=(l+r)>>1;
dfs(l,mid,now<<1);dfs(mid+1,r,now<<1|1);
cur=book[now];
}
vector<int> res;
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int n,q;
scanf("%d%d",&n,&q);
for(int i=1;i<=q;i++)
{
int l,r,x;
scanf("%d%d%d",&l,&r,&x);
se.update(l,r,x,1,n,1);
}
cur=1;
dfs(1,n,1);
for(int i=1;i<=n;i++)
if(ans[i])
res.pb(i);
printf("%d\n",int(res.size()));
for(auto i:res)
printf("%d ",i);
printf("\n");
return 0;
}