题解 | Flower Dance-2019牛客暑期多校训练营第八场I题

题目来源于牛客竞赛:https://ac.nowcoder.com/acm/contest/discuss
题目描述:
在这里插入图片描述
输入描述:
在这里插入图片描述
输出描述:
在这里插入图片描述
示例1:
在这里插入图片描述
题解:
在这里插入图片描述
代码:
#include
#include
#include
using namespace std;
typedef long long LL;
#define N 300000 + 5
#define M 1048576 + 5
#define mp make_pair
#define ls(x) x << 1
#define rs(x) x << 1 | 1

int n, m, q, sz, L[N], R[N], Fa[N], Le[N], Ri[N], Del[M];
LL Sum[M], Ans[N];
vector Vec[N];
bool Flag[N];

struct Operation
{
int x, op, l, r, id, a;
Operation() {}
Operation(int x, int op, int l, int r, int id, int a)
: x(x), op(op), l(l), r®, id(id), a(a) {
}
bool operator < (const Operation &obj) const
{
return mp(x, op) < mp(obj.x, obj.op);
}
}Op[N << 2];

void dfs(int st)
{
int ord = 0;
vector Sta;
Sta.push_back(st);
while (!Sta.empty())
{
int z = Sta.back();
if (!Le[z]) Le[z] = ++ ord;
for (; !Vec[z].empty() && Vec[z].back() == Fa[z]; Vec[z].pop_back()) ;
if (!Vec[z].empty())
{
int d = Vec[z].back();
Fa[d] = z, Sta.push_back(d);
Vec[z].pop_back();
}
else Ri[z] = ord, Sta.pop_back();
}
}

inline void apply(int x, int l, int r, int k)
{
Del[x] += k, Sum[x] += 1LL * (r - l + 1) * k;
}

inline void push(int x, int l, int r)
{
if (Del[x])
{
int mid = l + r >> 1;
apply(ls(x), l, mid, Del[x]);
apply(rs(x), mid + 1, r, Del[x]);
Del[x] = 0;
}
}

void Modify(int x, int l, int r, int s, int t, int k)
{
if (l == s && r == t)
{
apply(x, l, r, k);
return ;
}
push(x, l, r);
int mid = l + r >> 1;
if (t <= mid)
Modify(ls(x), l, mid, s, t, k);
else if (s > mid)
Modify(rs(x), mid + 1, r, s, t, k);
else Modify(ls(x), l, mid, s, mid, k), Modify(rs(x), mid + 1, r, mid + 1, t, k);
Sum[x] = Sum[ls(x)] + Sum[rs(x)];
}

LL Query(int x, int l, int r, int s, int t)
{
if (l == s && r == t)
return Sum[x];
push(x, l, r);
int mid = l + r >> 1;
if (t <= mid)
return Query(ls(x), l, mid, s, t);
else if (s > mid)
return Query(rs(x), mid + 1, r, s, t);
else return Query(ls(x), l, mid, s, mid) + Query(rs(x), mid + 1, r, mid + 1, t);
}

int main()
{
scanf("%d%d", &n, &m);
L[1] = 1, R[1] = n, Flag[1] = true;
for (int i = 1, u, v, l, r; i <= m; i ++)
{
scanf("%d%d%d%d", &u, &v, &l, &r);
Flag[v] = true;
Vec[u].push_back(v);
L[v] = l, R[v] = r;
}
dfs(1);
for (int i = 1; i <= m + 1; i ++)
Op[++ sz] = Operation(Le[i], 0, L[i], R[i], 0, 1);
scanf("%d", &q);
for (int i = 1, u, l, r; i <= q; i ++)
{
scanf("%d%d%d", &u, &l, &r);
Op[++ sz] = Operation(Le[u] - 1, 1, l, r, i, -1);
Op[++ sz] = Operation(Ri[u], 1, l, r, i, 1);
}
sort(Op + 1, Op + sz + 1);
for (int i = 1; i <= sz; i ++)
{
if (Op[i].op == 0)
Modify(1, 1, n, Op[i].l, Op[i].r, Op[i].a);
else Ans[Op[i].id] += Query(1, 1, n, Op[i].l, Op[i].r) * Op[i].a;
}
for (int i = 1; i <= q; i ++)
printf("%lld\n", Ans[i]);
return 0;
}
更多问题,更详细题解可关注牛客竞赛区,一个刷题、比赛、分享的社区。
传送门:https://ac.nowcoder.com/acm/contest/discuss

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值