CF981E Addition on Segments(线段树分治+bitset)

摘要:
通过观察这个问题,我们发现,如果每次都将某些操作更新到某个位置,我们可以通过保持位集来找到该位置的可能最大值,答案是对所有位置取或。因为我们发现,对于每个位置,位集上为1的数字必须是最大值。

观察本题,我们发现,如果某些操作每次都更新到了某个位置,那么我们可以通过维护bitset来发现这个对于这个位置来说的可能最大值

而且答案就是所有位置取一下或。因为我们发现对于每个位置,bitset上为1的那些数一定可以取到最大值。

但是这样过于暴力,我们发现这是一个区间操作,而区间操作一般和线段树相结合,因此采用线段树分治,先对这段操作影响到的区间打标记

最后从根一直往下传递,就能把所有影响到每个位置的答案计算出来

初始化0这个位置是合法的

CF981E Addition on Segments(线段树分治+bitset)第1张CF981E Addition on Segments(线段树分治+bitset)第2张
 #include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pll;
typedef pair<int,pll> plll;
const int N=1e6+10;
const int inf=0x3f3f3f3f;
const int mod=1e9+7;
bitset<10010> ans;
bitset<10010> s;
struct node{
    int l,r;
    vector<int> num;
}tr[N];
void build(int u,int l,int r){
    if(l==r){
        tr[u]={l,r};
    }
    else{
        tr[u]={l,r};
        int mid=l+r>>1;
        build(u<<1,l,mid);
        build(u<<1|1,mid+1,r);
    }
}
void modify(int u,int l,int r,int k){
    if(tr[u].l>=l&&tr[u].r<=r){
        tr[u].num.push_back(k);
        return ;
    }
    int mid=tr[u].l+tr[u].r>>1;
    if(l<=mid)
        modify(u<<1,l,r,k);
    if(r>mid)
        modify(u<<1|1,l,r,k);
}
void dfs(bitset<10010> x,int u){
    auto cur=x;
    for(auto a:tr[u].num){
        cur|=(cur<<a);
    }
    if(tr[u].l==tr[u].r){
        ans|=cur;
        return ;
    }
    int mid=tr[u].l+tr[u].r>>1;
    dfs(cur,u<<1);
    dfs(cur,u<<1|1);
}
int main(){
    ios::sync_with_stdio(false);
    int n,q;
    cin>>n>>q;
    s[0]=1;
    build(1,1,n);
    while(q--){
        int l,r,k;
        cin>>l>>r>>k;
        modify(1,l,r,k);
    }
    dfs(s,1);
    int cnt=0;
    for(int i=1;i<=n;i++){
        if(ans[i])
            cnt++;
    }
    cout<<cnt<<endl;
    for(int i=1;i<=n;i++){
        if(ans[i])
            cout<<i<<" ";
    }
    cout<<endl;
    return 0;
}
View Code

免责声明:文章转载自《CF981E Addition on Segments(线段树分治+bitset)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇RedisTemplate访问Redis数据结构(四)——SetUnity3D中的常用方法下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

POJ 2482 Stars in Your Window (线段树+扫描线+区间最值,思路太妙了)

该题和 黑书 P102 采矿 类似 参考链接:http://blog.csdn.net/shiqi_614/article/details/7819232http://blog.csdn.net/tsaid/article/details/6686907http://www.cnblogs.com/372465774y/archive/2012/07/28...

线段树-&amp;gt;面积并 Atlantis HDU

题目链接:https://cn.vjudge.net/problem/HDU-1542 题目大意:求面积并 具体思路:我们首先把矩形分割成一横条一横条的,然后对于每一个我们给定的矩形,我们将储存两个点,一个是左下角,一个是右上角。对于左下角的点,我们将他标记为-1,对于右上角的点,我们把它标记成1,-1代表这块区域的面积是需要减去的,1代表这块区域的面积是...

树状数组与线段树(一)

树状数组: 一共需要三个函数: ①lowbit(int x) ②add(int x,int p) ③query(int x) 1.动态求连续区间和 给定n个数组成的一个数列,规定有两种操作,一是修改某个元素,二是求子数列[a,b]的连续和。 输入格式 第一行包含两个整数n和m,分别表示数的个数和操作次数。 第二行包含n个整数,表示完整数列。 接下来m行,...

HDOJ 1166 敌兵布阵树状数组 线段树

敌兵布阵 Time Limit: 2000/1000 MS (Java/Others)Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 18120Accepted Submission(s): 7877 Problem Description C国的死对头A国这段时间正在进行军事演习...

[题解] bzoj 3600 没有人的算数 (替罪羊树+线段树)

- 传送门 - http://www.lydsy.com/JudgeOnline/problem.php?id=3600   - 思路 - 区间操作是线段树无疑,难点在于如何考虑这些数对的大小关系. 我们考虑一下平衡树,如果在平衡树中每个节点放一个数对,我们规定中序遍历前面的数对大于后面的,那么对于任意一个新数对(x,y)插入时只需知道x,y与每个节点的数...

[POJ1195] Mobile phones(二维树状数组)

题目链接:http://poj.org/problem?id=1195 题意:四种操作: 0:初始化一个S*S的零矩阵 1:点(x,y)是值+A 2:查询一个子矩阵里所有数的和 3:退出 线段树由于不能在两棵树之间传递标记,所以这种求和的操作非常难处理。 改学了一下而为树状数组,发现可是比二维线段树简单多了。 记得之前曾经看过zkw线段树的ppt讲稿,好像...