2020牛客寒假算法基础集训营4 H坐火车

题目描述

牛牛是一名喜欢旅游的同学,在来到渡渡鸟王国时,坐上了颜色多样的火车。
牛牛同学在车上,车上有 n 个车厢,每一个车厢有一种颜色。
他想知道对于每一个正整数 $ x in [1, n] $ 中,集合 $ x in [1, n],{ (i, x, j) | i < x < j, l_x le col_i = col_j le r_x } $中包含多少个元素
换句话说,就是要求每一个车厢两边有多少对颜色相同的车厢,并且这一对车厢的颜色要在$ l_x$到 $r_x$ 之间。其中 $col_i$代表 i 号车厢的颜色,$l_x,r_x$ 代表颜色的限制。

输入描述:

第一行一个正整数n。
第二行 n 个三元组,每个三元组包括三个正整数 (coli, li, ri),输入中没有括号,这 3n 个正整数之间均只用空格隔开,详见样例。
$ 1leq nleq 5 imes10^5, 1leq col_i,l_i,r_ileq 5 imes10^5. $

输出描述:

输出一行 n 个非负整数代表答案。

输入

5
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

输出

0 3 4 3 0

传送门:

https://ac.nowcoder.com/acm/contest/3005/H

思路:

首先维护一个关于颜色的前缀和$ ans $数组。$ ans[i] $代表 颜色在$ 1-i $之间的数量有多少。

如果我们已经知道$ x-1 $处的答案,如何维护这个数组得出$ x $处的答案呢?所以要加上$ x-1 $和后面的匹配数量(用$ r $数组维护)。

那么计算 $ x $处的答案之前要先减去 $ x $这点对前面的影响($ l $数组维护),为什么计算$ x $处的答案之前不减去 $ x $和后面的匹配数量呢?

因为 $ x $和后面所匹配的数量还没有加到 $ ans $数组里面。所以$ x $处的答案就是$ query(ans[r_x])-query(ans[l_x-1]) $.

代码:

 1 #include<bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 typedef long long ll;
 6 
 7 ll ans[500005];
 8 ll l[500005];
 9 ll r[500005];
10 
11 struct node
12 {
13     int c;
14     int l;
15     int r;
16 
17 };
18 
19 node col[500005];
20 
21 int n;
22 void add(int x, ll y)
23 {
24     for(; x <= n; x += x & -x)
25         ans[x] += y;
26 }
27 
28 ll query(int x)
29 {
30     ll sum = 0;
31     for(; x; x -= x & -x)
32         sum += ans[x];
33     return sum;
34 }
35 int main()
36 
37 {
38     scanf("%d", &n);
39 
40     for(int i = 1; i <= n; i++)
41     {
42         scanf("%d%d%d", &col[i].c, &col[i].l, &col[i].r);
43         r[col[i].c]++;
44     }
45 
46     for(int i = 1; i <= n; i++)
47     {
48 
49         add(col[i].c, -l[col[i].c]);
50         printf("%lld ", query(col[i].r) - query(col[i].l - 1) );
51         add(col[i].c, --r[col[i].c]);
52         l[col[i].c]++;
53     }
54 }
原文地址:https://www.cnblogs.com/yyaoling/p/12305326.html