hdu 3727 Jewel (可持久化线段树+bit)

时间:2023-03-09 20:08:31
hdu 3727 Jewel (可持久化线段树+bit)

链接: http://acm.hdu.edu.cn/showproblem.php?pid=3727

题意:

对一段序列进行四种操作:

Insert x :在序列尾部插入一个x;

Query_1 s t k : 求区间[s,t]中第k小的数

Query_2 x: 求x在序列中的排名

Query_3 k:求序列中第k小的数

思路;

第2,4个操作明显就是很裸的主席树求第k小。第3个操作我们可以单独用个树状数组维护,第一个操作因为会对序列造成影响,我们可以对所有操作进行离线处理,

分析完后可以发现这应该是一道比较简单的题。

主席树写搓了。。找了半天的错。。自闭

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mid int m = (l + r) >> 1
#pragma comment(linker, "/STACK:102400000,102400000")
const int M = 2e5 + ;
int c[M],ls[M*],rs[M*],sum[M*],a[M],root[M],num;
ll ans1,ans2,ans3;
int n,len,cnt,idx;
void add(int x){
while(x <= len){
c[x] += ;
x += (x&-x);
}
} int getsum(int x){
int ans = ;
while(x){
ans += c[x];
x -= (x&-x);
}
return ans;
} void update(int &now,int l,int r,int p){
int old = now; now = ++idx;
ls[now] = ls[old]; rs[now] = rs[old];
sum[now] = sum[old] + ;
if(l == r) return ;
mid;
if(p <= m) update(ls[now],l,m,p);
else update(rs[now],m+,r,p);
} int query_1(int old,int now,int l,int r,int k){
if(l == r)
return l;
mid;
int ret = sum[ls[now]] - sum[ls[old]];
//cout<<sum[ls[now]]<<" "<<sum[ls[old]]<<endl;
if(ret >= k)
return query_1(ls[old],ls[now],l,m,k);
else
return query_1(rs[old],rs[now],m+,r,k-ret);
} int query_3(int &now,int l,int r,int k){
if(l == r) return l;
mid;
int ret = sum[ls[now]];
if(ret >= k) return query_3(ls[now],l,m,k);
else return query_3(rs[now],m+,r,k - ret);
} int find(int x){
return lower_bound(a+,a++len,x) - a;
} void init(){
cnt = ; idx = ; len = ,num = ;
ans1 = ; ans2 = ;ans3 = ;
memset(c,,sizeof(c));
memset(ls,,sizeof(ls));
memset(rs,,sizeof(rs));
memset(sum,,sizeof(sum));
memset(root,,sizeof(root));
} struct node{
int x,s,t,k;
}q[M];
char op[M][];
int main()
{
int cas = ;
while(scanf("%d",&n)!=EOF){
init();
for(int i = ;i <= n;i ++){
scanf("%s",op[i]);
if(op[i][] == 'I'){
scanf("%d",&q[i].x);
a[++cnt] = q[i].x;
}
else{
if(op[i][] == '')
scanf("%d%d%d",&q[i].s,&q[i].t,&q[i].k);
else if(op[i][] == '')
scanf("%d",&q[i].x),a[++cnt] = q[i].x;
else if(op[i][] == '')
scanf("%d",&q[i].k);
}
}
sort(a+,a++cnt);
len = unique(a+,a++cnt) - a-;
for(int i = ;i <= n;i ++){
if(op[i][] == 'I'){
int fx = find(q[i].x);
root[num] = root[num-];
update(root[num],,len,fx);
num++;
add(fx);
}
else{
if(op[i][] == '')
ans1 += a[query_1(root[q[i].s-],root[q[i].t],,len,q[i].k)];
else if(op[i][] == ''){
int fx = find(q[i].x);
ans2 += getsum(fx-) + ;
}
else if(op[i][] == '')
ans3 += a[query_3(root[num-],,len,q[i].k)];
//cout<<ans1<<" "<<ans2<<" "<<ans3<<" "<<endl;
}
}
printf("Case %d:\n",cas++);
printf("%lld\n%lld\n%lld\n",ans1,ans2,ans3);
}
return ;
}
/*
3 0
1 0
3 1
2 1
*/