[树状数组]洛谷 P3586 LOG 题解
这个结论的说明其实洛谷的第一篇题解写的很清楚了 qwq
相当于是根据离散值建权值树状数组,动态维护大于 s 的种类的数量,和小于 s 的种类的和,然后在维护一下这个数组本身的值就行了。
注意哦,这里离散是要把查询更新一起离线离散的
具体实现还是有点麻烦的,好像别的题解都没仔细写,那么我来详细展开一下罢
#include <bits/stdc++.h>
#define int long long
#define qwq return 0
#define ri register int
#define N 1000007
#define lowbit(x) (x & -x)
int len , n , m , a[N] , b[N] , d[N] , tree1[N] , tree2[N];
struct option {
char type;
int c/*k*/ , s/*a*/;
}opt[N << 1];
using namespace std;
inline void update(int *s , int x , int k) {
if(!x) {
return;
}
while(x <= len) {
s[x] += k;
x += lowbit(x);
}
}
inline int sum(int *s , int x) {
int r = 0;
while(x) {
r += s[x];
x -= lowbit(x);
}
return r;
}
signed main()
{
cin >> n >> m;
for(ri i = 1; i <= m; ++i) {
cin >> opt[i].type >> opt[i].c >> opt[i].s;
b[i] = a[i] = opt[i].s;
}
sort(a + 1 , a + m + 1);
len = unique(a + 1 , a + m + 1) - a - 1;
for(ri i = 1; i <= m ; ++i) {
b[i] = lower_bound(a + 1 , a + len + 1 , b[i]) - a; //离散化后,每个命令的离散值
}
for(ri i = 1; i <= m; ++i) {
switch(opt[i].type) {
case 'U' : {
update(tree1 , d[opt[i].c] , - 1);//由于是修改,要先把原来的值给去了
update(tree1 , b[i] , 1); //再加上新值
update(tree2 , d[opt[i].c] , -a[d[opt[i].c]]); //这里更改时要用离散前的值
update(tree2 , b[i] , a[b[i]]);
d[opt[i].c] = b[i];//d相当于是我们动态维护的这个数组本身
break;
}
case 'Z' : {
int y = sum(tree1 , len) - sum(tree1 , b[i] - 1);//大于s数量
int x = sum(tree2 , b[i] - 1) + y * opt[i].s;//小于s的和
//把大于s的全剪成s,其他的加上即可
cout << ((x >= opt[i].c * opt[i].s) ? "TAK" : "NIE") <<'\n';
break;
}
}
}
qwq;
}