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 education lessons. The end of the term is very soon, but, unfortunately, Alex still hasn‘t attended a single lesson!

Since Alex doesn‘t want to get expelled, he wants to know the number of working days left until the end of the term, so he can attend physical education lessons during these days. But in BSU calculating the number of working days is a complicated matter:

There are n days left before the end of the term (numbered from 1 to n), and initially all of them are working days. Then the university staff sequentially publishes q orders, one after another. Each order is characterised by three numbers l, r and k:

  • If k?=?1, then all days from l to r (inclusive) become non-working days. If some of these days are made working days by some previous order, then these days still become non-working days;
  • If k?=?2, then all days from l to r (inclusive) become working days. If some of these days are made non-working days by some previous order, then these days still become working days.

Help Alex to determine the number of working days left after each order!

Input

The first line contains one integer n, and the second line — one integer q (1?≤?n?≤?109, 1?≤?q?≤?3·105) — the number of days left before the end of the term, and the number of orders, respectively.

Then q lines follow, i-th line containing three integers li, ri and *k**i* representing i-th order (1?≤?li?≤?ri?≤?n, 1?≤?*k**i*?≤?2).

Output

Print q integers. i-th of them must be equal to the number of working days left until the end of the term after the first i orders are published.

Example

Input

461 2 13 4 12 3 21 3 22 4 11 4 2

Output

202314

思路:

区间很大,询问不是很大,经典的动态开点线段树问题,

即在处理询问的过程中,需要用到一个区间再到线段树中去申请一个位置给它。

大概需要开不到\(2*q*log(x)\) 左右个节点即可完成。x是区间的最大长度。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <iomanip>
#define ALL(x) (x).begin(), (x).end()
#define sz(a) int(a.size())
#define rep(i,x,n) for(int i=x;i<n;i++)
#define repd(i,x,n) for(int i=x;i<=n;i++)
#define pii pair<int,int>
#define pll pair<long long ,long long>
#define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define MS0(X) memset((X), 0, sizeof((X)))
#define MSC0(X) memset((X), '\0', sizeof((X)))
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define eps 1e-6
#define gg(x) getInt(&x)
#define chu(x) cout<<"["<<#x<<" "<<(x)<<"]"<<endl
#define du3(a,b,c) scanf("%d %d %d",&(a),&(b),&(c))
#define du2(a,b) scanf("%d %d",&(a),&(b))
#define du1(a) scanf("%d",&(a));
using namespace std;
typedef long long ll;
ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
ll lcm(ll a, ll b) {return a / gcd(a, b) * b;}
ll powmod(ll a, ll b, ll MOD) {a %= MOD; if (a == 0ll) {return 0ll;} ll ans = 1; while (b) {if (b & 1) {ans = ans * a % MOD;} a = a * a % MOD; b >>= 1;} return ans;}
void Pv(const vector<int> &V) {int Len = sz(V); for (int i = 0; i < Len; ++i) {printf("%d", V[i] ); if (i != Len - 1) {printf(" ");} else {printf("\n");}}}
void Pvl(const vector<ll> &V) {int Len = sz(V); for (int i = 0; i < Len; ++i) {printf("%lld", V[i] ); if (i != Len - 1) {printf(" ");} else {printf("\n");}}}

inline void getInt(int *p);
const int maxn = 300010 * 30 * 2;
const int inf = 0x3f3f3f3f;
/*** TEMPLATE CODE * * STARTS HERE ***/
struct node {
    int lson;
    int rson;
    int val;
    int laze;
} segment_tree[15001000 ];
int n, m;
int tot = 1;
void pushdown(int rt, int l, int r, int mid)
{
    if (segment_tree[rt].val) {
        segment_tree[segment_tree[rt].lson].val = (mid - l + 1);
        segment_tree[segment_tree[rt].rson].val = ( r - mid  );
    } else {
        segment_tree[segment_tree[rt].lson].val = 0;
        segment_tree[segment_tree[rt].rson].val = 0;
    }
    segment_tree[rt].laze = 0;
    segment_tree[segment_tree[rt].lson].laze = 1;
    segment_tree[segment_tree[rt].rson].laze = 1;
}
void update(int rt, int ql, int qr, int l, int r, int op)
{
    if (l <= ql && qr <= r) {
        segment_tree[rt].laze = 1;
        segment_tree[rt].val = (qr - ql + 1) * op;
        return;
    }
    if (!segment_tree[rt].lson) {
        segment_tree[rt].lson = ++tot;
    }
    if (!segment_tree[rt].rson) {
        segment_tree[rt].rson = ++tot;
    }
    if (segment_tree[rt].laze) {
        pushdown(rt, ql, qr, qr + ql >> 1);
    }
    int mid = (ql + qr) >> 1;
    if (l <= mid) {
        update(segment_tree[rt].lson, ql, mid, l, r, op);
    }
    if (r > mid) {
        update(segment_tree[rt].rson, mid + 1, qr, l, r, op);
    }
    int ls = segment_tree[rt].lson;
    int rs = segment_tree[rt].rson;
    segment_tree[rt].val = segment_tree[ls].val + segment_tree[rs].val;
}
int main()
{
    //freopen("D:\\code\\text\\input.txt","r",stdin);
    //freopen("D:\\code\\text\\output.txt","w",stdout);
    du2(n, m);
    while (m--) {
        int l, r, op;
        du3(l, r, op);
        if (op == 1) {
            update(1, 1, n, l, r, op);
        } else {
            update(1, 1, n, l, r, 0);
        }
        printf("%d\n", n - segment_tree[1].val );
    }
    return 0;
}

inline void getInt(int *p)
{
    char ch;
    do {
        ch = getchar();
    } while (ch == ' ' || ch == '\n');
    if (ch == '-') {
        *p = -(getchar() - '0');
        while ((ch = getchar()) >= '0' && ch <= '9') {
            *p = *p * 10 - ch + '0';
        }
    } else {
        *p = ch - '0';
        while ((ch = getchar()) >= '0' && ch <= '9') {
            *p = *p * 10 + ch - '0';
        }
    }
}

原文地址:https://www.cnblogs.com/qieqiemin/p/11622999.html

时间: 2024-08-29 12:37:59

Physical Education Lessons CodeForces - 915E (动态开点线段树)的相关文章

Physical Education Lessons Codeforces - 915E

http://codeforces.com/problemset/problem/915/E 大概有几种思路: 1.动态开点线段树+标记下传 #1.1标记永久化:想了一会没想出来 1.2可以先扫一遍询问把所有需要的点建出来,然后pushdown就不管没建出来的点了,空间跟标记永久化一样 2.离散化+线段树 3.用splay维护区间(估计没人愿意去写) 4.用一个set<pair<int,int>>记所有非工作日(或工作日)区间,修改就暴力找到相关的区间去改 由于每一次操作最多多出O

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

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

动态开点线段树 题目暗示了区间修改,所以我们自然想到了用线段树来维护非工作日的天数. 然而我们再看一下数据范围,天数n的范围是\(1 \le n \le 10^9\),像普通线段树一样预处理显然会爆空间. 天无绝人之路,我们看一下修改个数,$1\le q \le 3 \cdot 10^5 $, 比天数少很多,这也意味着,我们预先处理好的线段树有些节点并没有用 能否优化呢?答案是肯定的,这就是动态开点线段树,顾名思义,我们只要到用某个节点的时候,才分配一个点给它,这样使得我们使用的空间大大减少.其

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

动态开点线段树

用途 需要建立多棵独立的线段树 线段树维护的值域较大(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 第一

【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$,那么它们会开始聊天. 为了防止它们吵起来,请计算有多少对机器人可能会聊天. 题解 先膜一下大佬->这里 我们先按视野降序排序,这样一个一个考虑,如果后面的能看到前面,那前面的也肯定能看到后面 这样,就是对于每