CodeForces - 981E Addition on Segments(线段树+bitset优化01背包)

版权声明:Why is everything so heavy? https://blog.csdn.net/lzc504603913/article/details/82961722

E. Addition on Segments

time limit per test

2 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

Grisha come to a contest and faced the following problem.

You are given an array of size nn, initially consisting of zeros. The elements of the array are enumerated from 11 to nn. You perform qqoperations on the array. The ii-th operation is described with three integers lili, riri and xixi (1≤li≤ri≤n1≤li≤ri≤n, 1≤xi≤n1≤xi≤n) and means that you should add xixi to each of the elements with indices li,li+1,…,rili,li+1,…,ri. After all operations you should find the maximum in the array.

Grisha is clever, so he solved the problem quickly.

However something went wrong inside his head and now he thinks of the following question: "consider we applied some subset of the operations to the array. What are the possible values of the maximum in the array?"

Help Grisha, find all integers yy between 11 and nn such that if you apply some subset (possibly empty) of the operations, then the maximum in the array becomes equal to yy.

Input

The first line contains two integers nn and qq (1≤n,q≤1041≤n,q≤104) — the length of the array and the number of queries in the initial problem.

The following qq lines contain queries, one per line. The ii-th of these lines contains three integers lili, riri and xixi (1≤li≤ri≤n1≤li≤ri≤n, 1≤xi≤n1≤xi≤n), denoting a query of adding xixi to the segment from lili-th to riri-th elements of the array, inclusive.

Output

In the first line print the only integer kk, denoting the number of integers from 11 to nn, inclusive, that can be equal to the maximum in the array after applying some subset (possibly empty) of the given operations.

In the next line print these kk integers from 11 to nn — the possible values of the maximum. Print these integers in increasing order.

Examples

input

Copy

4 3
1 3 1
2 4 2
3 4 4

output

Copy

4
1 2 3 4 

input

Copy

7 2
1 5 1
3 7 2

output

Copy

3
1 2 3 

input

Copy

10 3
1 1 2
1 1 3
1 1 6

output

Copy

6
2 3 5 6 8 9 

Note

Consider the first example. If you consider the subset only of the first query, the maximum is equal to 11. If you take only the second query, the maximum equals to 22. If you take the first two queries, the maximum becomes 33. If you take only the fourth query, the maximum becomes 44. If you take the fourth query and something more, the maximum becomes greater that nn, so you shouldn't print it.

In the second example you can take the first query to obtain 11. You can take only the second query to obtain 22. You can take all queries to obtain 33.

In the third example you can obtain the following maximums:

  • You can achieve the maximim of 22 by using queries: (1)(1).
  • You can achieve the maximim of 33 by using queries: (2)(2).
  • You can achieve the maximim of 55 by using queries: (1,2)(1,2).
  • You can achieve the maximim of 66 by using queries: (3)(3).
  • You can achieve the maximim of 88 by using queries: (1,3)(1,3).
  • You can achieve the maximim of 99 by using queries: (2,3)(2,3).

题意:问你取区间求和操作的某些子集,能否得到最大值为X,输出所有能得到的最大值

解题思路:取子集问题,很容易想到01背包,关键是怎么用。有一种操作是用bitset去优化01背包

假设有5件物品,重量为 

1 1 2 3 3

那么他们组合能得到的重量种类为

1 2 3 4 5 6 7 9 10

用bitset表示就是 1101111111

那么对于每一个物品,我们做左移操作然后或一下即可继承之前的所有状态。假设现在有 一个bitset 表示能得到重量类型为1,2,3,4

1111

现在来了一个重量为6的物品,相当于bitset左移6位,然后把第六位置为1

111110000

这样子就表示能得到的重量为 10,9,8,7,6

然后再跟之前或一下

111111111

就代表现在的状态了

然后我们就可以建立线段树了,把所有的区间操作打上懒惰标记。

然后查询的时候,把所有标记下推到最底下,然后更新答案即可。下推不用真正的下推,直接计算即可。

#include <iostream>
#include <vector>
#include <string.h>
#include <algorithm>
#include <set>
#include <stdio.h>
#include <map>
#include <bitset>
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int MAXN = 10005;

vector<int> lazy[MAXN<<2];
void update(int L,int R,int W,int l,int r,int rt){
    if(L<=l&&r<=R){
        lazy[rt].push_back(W);
        return;
    }
    int m=(l+r)/2;
    if(L<=m)
        update(L,R,W,l,m,rt<<1);
    if(R>m)
        update(L,R,W,m+1,r,rt<<1|1);
}

bitset<MAXN> z,ans;

void query(bitset<MAXN> w,int l,int r,int rt){
    
    for(int i=lazy[rt].size()-1;i>=0;i--)//这里必须要从后往前,因为我们的操作是从前往后的,这样子才能使后面的操作自然溢出
        w|=(w<<lazy[rt][i]);
    if(l==r){
        ans|=w;
        return;
    }
    int m=(l+r)/2;
    query(w,l,m,rt<<1);
    query(w,m+1,r,rt<<1|1);
}

int main()
{
    int N,Q;
    int l,r,w;
    scanf("%d%d",&N,&Q);
    for(int i=0;i<Q;i++){
        scanf("%d%d%d",&l,&r,&w);
        update(l,r,w,1,N,1);
    }
    bitset<MAXN>  s;
    s[0]=1;
    query(s,1,N,1);
    int num=0;

    for(int i=1;i<=N;i++)
        if(ans[i])
            num++;

    cout<<num<<endl;
    for(int i=1;i<=N;i++)
        if(ans[i])
            cout<<i<<" ";


    return 0;
}

猜你喜欢

转载自blog.csdn.net/lzc504603913/article/details/82961722