CF915E Physical Education Lessons|动态开点线段树

动态开点线段树

题目暗示了区间修改,所以我们自然想到了用线段树来维护非工作日的天数。

然而我们再看一下数据范围,天数n的范围是\(1 \le n \le 10^9\),像普通线段树一样预处理显然会爆空间。

天无绝人之路,我们看一下修改个数,$1\le q \le 3 \cdot 10^5 $, 比天数少很多,这也意味着,我们预先处理好的线段树有些节点并没有用

能否优化呢?答案是肯定的,这就是动态开点线段树,顾名思义,我们只要到用某个节点的时候,才分配一个点给它,这样使得我们使用的空间大大减少。其余的与普通线段树大致是相同的。

最后再说一下,本题的数组要开大一些,否则会疯狂\(RE\)

代码奉上~

#include<bits/stdc++.h>
using namespace std;
int tree[15001000],lson[15001000],rson[15001000],tag[15001000],d;
long long n,q,l,r,k;
void freelazy(int x,int l,int r)
{
    int mid=(l+r)/2;
    if (tree[x])
    {
      tree[lson[x]]=(mid-l+1);
      tree[rson[x]]=(r-(mid+1)+1);
    }
    else
    {
      tree[lson[x]]=0;
      tree[rson[x]]=0;
    }
    tag[lson[x]]=1;
    tag[rson[x]]=1;
    tag[x]=0;
    //正常的懒标记下放操作
}
void add(int x,int l,int r,int ql,int qr,int sd)
{

    if (ql<=l&&qr>=r)
    {
        tree[x]=(r-l+1)*sd;tag[x]=1;
        return ;
    }
    if (!lson[x])
    {
        d++;
        lson[x]=d;
    }
    if (!rson[x])
    {
        d++;
        rson[x]=d;
    }//要用就开点
    //上面要记得记录左右儿子
    if (tag[x]) freelazy(x,l,r);
    int mid=(l+r)/2;
    if (ql>mid)
    {
        add(rson[x],mid+1,r,ql,qr,sd);
    }
    else
    if (qr<=mid)
    {
        add(lson[x],l,mid,ql,qr,sd);
    }
    else
    {
        add(lson[x],l,mid,ql,mid,sd);
        add(rson[x],mid+1,r,mid+1,qr,sd);
    }
    tree[x]=tree[lson[x]]+tree[rson[x]];
    //正常的线段树操作
}
int main()
{
    cin>>n>>q;d=1;
    for (int i=1;i<=q;i++)
    {
        scanf("%d%d%d",&l,&r,&k);//本题用cin、cout会有超时风险
        if (l>r) swap(l,r);
        if (k==1)
        {
            add(1,1,n,l,r,k);
        }
        else
        {
            add(1,1,n,l,r,0);
        }
        printf("%d\n",n-tree[1]);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/fmj123/p/CF915E.html

时间: 2024-08-29 01:02:44

CF915E Physical Education Lessons|动态开点线段树的相关文章

Educational Codeforces Round 36 (Rated for Div. 2) E. Physical Education Lessons(动态开点线段树)

链接: https://codeforces.com/problemset/problem/915/E 题意: This year Alex has finished school, and now he is a first-year student of Berland State University. For him it was a total surprise that even though he studies programming, he still has to atten

Physical Education Lessons CodeForces - 915E (动态开点线段树)

Physical Education Lessons CodeForces - 915E This year Alex has finished school, and now he is a first-year student of Berland State University. For him it was a total surprise that even though he studies programming, he still has to attend physical

CF915E Physical Education Lessons

题意: Alex高中毕业了,他现在是大学新生.虽然他学习编程,但他还是要上体育课,这对他来说完全是一个意外.快要期末了,但是不幸的Alex的体育学分还是零蛋! Alex可不希望被开除,他想知道到期末还有多少天的工作日,这样他就能在这些日子里修体育学分.但是在这里计算工作日可不是件容易的事情: 从现在到学期结束还有 n 天(从 1 到 n 编号),他们一开始都是工作日.接下来学校的工作人员会依次发出 q 个指令,每个指令可以用三个参数 l,r,k 描述: 如果 k=1,那么从 l 到 r (包含端

动态开点线段树

用途 需要建立多棵独立的线段树 线段树维护的值域较大(1e9),但是操作次数较少(1e5) 特征 类似主席树的原理,动态分配每个树节点的位置(lson[],rson[]),每次只更新一条链,但是主席树是建立一颗新的树,动态开点线段树是在一棵树上不断添加节点(还是一棵树) 类似线段树的原理,push_down区间修改,push_up区间查询 例题 1.维护值域较大,线段树区间修改 cf915e https://codeforces.com/contest/915/problem/E 题意: q(3

【BZOJ-4636】蒟蒻的数列 动态开点线段树 ||(离散化) + 标记永久化

4636: 蒟蒻的数列 Time Limit: 30 Sec  Memory Limit: 256 MBSubmit: 247  Solved: 113[Submit][Status][Discuss] Description 蒟蒻DCrusher不仅喜欢玩扑克,还喜欢研究数列 题目描述 DCrusher有一个数列,初始值均为0,他进行N次操作,每次将数列[a,b)这个区间中所有比k小的数改为k,他想知 道N次操作后数列中所有元素的和.他还要玩其他游戏,所以这个问题留给你解决. Input 第一

Codeforces 803G Periodic RMQ Problem ST表+动态开节点线段树

思路: (我也不知道这是不是正解) ST表预处理出来原数列的两点之间的min 再搞一个动态开节点线段树 节点记录ans 和标记 lazy=-1 当前节点的ans可用  lazy=0 没被覆盖过 else 区间覆盖 push_up的时候要注意好多细节,, 数组尽量往大开 //By SiriusRen #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const in

【bzoj3939】[Usaco2015 Feb]Cow Hopscotch 动态开点线段树优化dp

题目描述 Just like humans enjoy playing the game of Hopscotch, Farmer John's cows have invented a variant of the game for themselves to play. Being played by clumsy animals weighing nearly a ton, Cow Hopscotch almost always ends in disaster, but this has

【bzoj4999】This Problem Is Too Simple! 树链剖分+动态开点线段树

题目描述 给您一颗树,每个节点有个初始值. 现在支持以下两种操作: 1. C i x(0<=x<2^31) 表示将i节点的值改为x. 2. Q i j x(0<=x<2^31) 表示询问i节点到j节点的路径上有多少个值为x的节点. 输入 第一行有两个整数N,Q(1 ≤N≤ 100,000:1 ≤Q≤ 200,000),分别表示节点个数和操作个数. 下面一行N个整数,表示初始时每个节点的初始值. 接下来N-1行,每行两个整数x,y,表示x节点与y节点之间有边直接相连(描述一颗树).

CF1045G AI robots(动态开点线段树)

题意 火星上有$N$个机器人排成一行,第$i$个机器人的位置为$x_{i}$,视野为$r_{i}$,智商为$q_{i}$.我们认为第$i$个机器人可以看到的位置是$[x_{i}-r_{i},x_{i}+r_{i}]$.如果一对机器人相互可以看到,且它们的智商$q_{i}$的差距不大于$K$,那么它们会开始聊天. 为了防止它们吵起来,请计算有多少对机器人可能会聊天. 题解 先膜一下大佬->这里 我们先按视野降序排序,这样一个一个考虑,如果后面的能看到前面,那前面的也肯定能看到后面 这样,就是对于每