您的位置:首页 > 其它

CodeForces 669E Little Artem and Time Machine(主席树+树状数组)

2016-04-25 22:13 369 查看
题意:维护一个multiset,给出n次询问,有三种类型的操作,分别是增加元素,删除元素,查询元素数量,

每次询问操作有一个时间和一个元素,询问这个时间的时候这个元素的数量。

思路:主席树+树状数组,其中时间可以看成主席树的位置,然后就是用树状数组动态修改主席树中的元素,离散化一下时间和元素然后每次查询输出。

树状数组每个结点都是一棵线段树,表示一个区间内所有元素的数量情况,具体见

动态主席树

#include <bits/stdc++.h>
#define eps 1e-6
#define LL long long
#define pii pair<int, int>
#define pb push_back
#define mp make_pair
//#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
const int maxn = 100100;
const int M = 20000000;
int n, m, tot;
int t[maxn];
int lson[M], rson[M], c[M];
int S[maxn];
struct Query {
int kind;
int pos, val;
} query[maxn];

void Init_hash(int k) {
sort(t, t+k);
m = unique(t, t+k) - t;
}

int Hash(int x) {
return lower_bound(t, t+m, x) - t;
}

int build(int l, int r) {
int root = tot++;
c[root] = 0;
if(l != r) {
int mid = (l+r) >> 1;
lson[root] = build(l, mid);
rson[root] = build(mid+1, r);
}
return root;
}
int Insert(int root, int pos, int val) {
int newroot = tot++, tmp = newroot;
int l = 0, r = m-1;
c[newroot] = c[root] + val;
while(l < r) {
int mid = (l+r)>>1;
if(pos <= mid) {
lson[newroot] = tot++; rson[newroot] = rson[root];
newroot = lson[newroot]; root = lson[root];
r = mid;
}
else {
rson[newroot] = tot++; lson[newroot] = lson[root];
newroot = rson[newroot]; root = rson[root];
l = mid+1;
}
c[newroot] = c[root] + val;
}
return tmp;
}

int lowbit(int x) {
return x&(-x);
}
int use[maxn];
void add(int x, int pos, int d) {
while(x <= n) {
S[x] = Insert(S[x], pos, d);
x += lowbit(x);
}
}
int Sum(int x) {
int ret = 0;
while (x > 0) {
ret += c[use[x]];
x -= lowbit(x);
}
return ret;
}
int solve(int pos, int k) {
int l = 0, r = m-1;
for (int i = pos; i; i -= lowbit(i)) use[i] = S[i];
while (l < r) {
int mid = (l+r) >> 1;
if(mid >= k) {
r = mid;
for(int i = pos; i; i -= lowbit(i)) use[i] = lson[use[i]];
}
else {
l = mid + 1;
for(int i = pos; i; i -= lowbit(i)) use[i] = rson[use[i]];
}
}
return Sum(pos);
}
int tmp[maxn];
int main() {
//freopen("input.txt", "r", stdin);
scanf("%d", &n);
tot = 0;
m = 0;
for(int i = 1; i <= n; i++) {
scanf("%d%d%d", &query[i].kind, &query[i].pos, &query[i].val);
t[m++] = query[i].val;
tmp[i] = query[i].pos;
}
sort(tmp+1, tmp+n+1);
for (int i = 1; i <= n; i++)
query[i].pos = lower_bound(tmp+1, tmp+n+1, query[i].pos) - tmp;
Init_hash(m);
S[0] = build(0, m-1);
for (int i = 1; i <= n; i++) S[i] = S[0];
for (int i = 1; i <= n; i++) {
if (query[i].kind == 1)
add(query[i].pos, Hash(query[i].val), 1);
else if (query[i].kind == 2)
add(query[i].pos, Hash(query[i].val), -1);
else
printf("%d\n", solve(query[i].pos, Hash(query[i].val)));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息