ycz有很多很多的妹子(ycz:瞎说)
机房神犇ycz有n个青梅竹马,她们分别住在1~n号城市中。小时候的她们美丽可爱,但是由于女大十八变,有些妹子的颜值发生了变化,但是十分重感情的ycz神犇不忍心抛弃她们,于是记录下来了她们颜值变化的值,我们用Cxy表示第x个城市的妹子的颜值下降了y。长大之后的ycz非常有魅力,有许多妹子被ycz迷得神魂颠倒,我们用Ixy表示第x个城市有一个妹子喜欢上了ycz,她的颜值为y(y有可能是负数,但是ycz来者不拒)。但在中途有一些妹子和ycz吵架了,于是就分手了,我们用Dx表示第x个妹子和ycz分手了。
最近神犇ycz要去全国各地找他的妹子们,为了方便计算,我们珂以把ycz的妹子所在的城市当作是一条直线,并且挨在一起。神犇ycz由于忙于和他的妹子们联系此时已经很累了,于是交给你一个这样的任务:他想知道他在某个时间去找他的所有妹子们珂以获得多大的愉悦度,这个愉悦度为他找的妹子的颜值数,你要做的就是求出这个愉悦度之和(注意长大后妹子们的颜值可能为负数/滑稽)。
注意:每个城市只允许有一个妹子,也就是说后来喜欢上ycz的妹子会赶走之前这个城市喜欢ycz的妹子~~(一城不容二女)~~。
UPD:
青梅竹马都是喜欢ycz的。
分手的第x个妹子不是第x城市的妹子,是指从前往后数第x个有妹子的城市的妹子
青梅竹马长大后就是妹子
修改的值y不为负数,但是颜值减去之后可能为负数
第一行两个正整数n和m (1<=n<=100000)(1<=n<=100000)
第二行为n个整数ai,表示小时候ycz的青梅竹马的颜值(1<=ai<=10^9)
接下来m行,每行为一条信息,每条信息可能是下面的一种:
Cxy表示第x个城市的妹子的颜值下降了y
Ixy表示在第x个城市有一个颜值为y的妹子迷上了ycz
Dx表示第x个妹子和ycz分手了
Q表示ycz现在想知道如果现在去找他所有的妹子们珂以获得多大的愉悦度
说明:妹子们居住的城市编号最大为5×10^5
对于每一个QQ输出一个整数
输入 #1
5 10
1 2 3 4 5
Q
C 3 2
Q
I 6 6
Q
D 4
Q
C 5 2
I 7 9
Q
输出 #1
15
13
19
15
22
样例解释:
妹子颜值变化如下,删除的就没写在下面了。
1 2 1 4 5
1 2 1 4 5 6
1 2 1 5 6
1 2 1 3 6
1 2 1 3 6 9
对于30%的数据1<=n,m<=10
对于70%的数据1<=n,m<=1000
对于100%的数据1<=n,m<=100000,1<=ai,y<=10^9
使用数组a记录每个城市的女生的颜值,数组has记录每个城市是否有女生,若有则为TRUE(1),没有则为FALSE(0)。 数组bit相当于是has的树状数组,提供两个操作:
- add(int x, int k),在x位置增加k,那么add(x, 1)就表示原本x城市没有女生,现在有了;而add(x, -1)则表示原来有女生的城市x现在没有了。
- get_sum(int x),返回[1, x]的和。get_sum(x)的实际意义就是[1, x]中有女生的城市的数量。
最大城市编号不超过500000,#define maxcity 500000,数组的大小都开maxcity + 1。用sum记录颜值和。
- 输入时可确定a[1] ~ a[n]的值,此时sum即a[1] ~ a[n]之和。a[n + 1] ~ a[maxcity]为 0。
- has[1] ~ has[n]为TRUE,has[n + 1] ~ has[maxcity]为FALSE。
- bit初始全0,对于i属于[1, n],对bit进行修改: add(i, 1)
更新sum和a[x]: sum -= y; a[x] -= y;
has和bit不变。
更新sum和a[x]:
sum += y - a[x];
a[x] = y;
若has[x]为FALSE,即I操作之前x城市没有女生,则更新has[x]为TRUE,并且add(x, 1)
首先需要找到第x个有女生的城市。
二分 + 树状数组区间查询:
从[1, maxcity]开始二分。对于二分的mid,若get_sum[mid] < x,则[1, mid]区间内的女生不够x个,则向右继续二分。若get_sum[mid] > x,则[1, mid]区间内的女生多于x个了,继续向左二分。
当get_sum[mid] == x时,[1, mid]区间内的女生正好有x个,注意此时若has[mid]为TRUE,即mid城市有女生,那么mid就是第x个有女生的城市。但若has[mid]为FALSE,
则第x个有女生的城市在mid之前,只是第x个有女生的城市到mid之间没有城市有女生,所以[1, mid]内仍然是x个女生。这种情况下也要向左二分。
找到正确的mid之后更新sum和a[mid]: sum -= a[mid]; a[mid] = 0;,更新has[mid]为FALSE,并add(mid, -1)
输出sum即可。
#include "stdio.h"
#include "stdlib.h"
typedef unsigned char bool;
#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif
#define maxcity 500000
long long a[maxcity + 1];
int bit[maxcity + 1];
bool has[maxcity + 1];
int lowbit(int x) {
return x & -x;
}
void add(int x, int k) {
for (; x <= maxcity; x += lowbit(x)) {
bit[x] += k;
}
}
int get_sum(int x) {
int result = 0;
for (; x > 0; x -= lowbit(x)) {
result += bit[x];
}
return result;
}
int main() {
int n, m;
scanf("%d %d", &n, &m);
long long sum = 0;
int i;
for (i = 1; i < maxcity + 1; i++) bit[i] = 0;
for (i = 1; i <= n; i++) {
scanf("%lld", a + i);
sum += a[i];
add(i, 1);
has[i] = TRUE;
}
for (; i < maxcity + 1; i++) {
a[i] = 0;
has[i] = FALSE;
}
char cmd;
int x, y;
for (i = 0; i < m; i++) {
scanf(" %c", &cmd);
switch (cmd) {
case 'C': {
scanf("%d %d", &x, &y);
sum -= y;
a[x] -= y;
break;
}
case 'I': {
scanf("%d %d", &x, &y);
sum += y - a[x];
a[x] = y;
if (!has[x]) {
has[x] = TRUE;
add(x, 1);
}
break;
}
case 'D': {
scanf("%d", &x);
int left = 1, right = maxcity, mid, s;
while (left <= right) {
mid = (left + right) / 2;
s = get_sum(mid);
if (s == x) {
if (has[mid]) {
sum -= a[mid];
a[mid] = 0;
has[mid] = FALSE;
add(mid, -1);
break;
}
else {
right = mid - 1;
}
}
else if (s < x) {
left = mid + 1;
}
else {
right = mid - 1;
}
}
break;
}
case 'Q': {
printf("%lld\n", sum);
break;
}
default:
break;
}
}
return 0;
}Written with StackEdit.