您的位置:首页 > 其它

hdu 3727 Jewel(主席树学习第四弹)

2015-10-13 21:11 417 查看

题目链接:

hdu 3727

题目大意:

给出n个操作,插入一个数,或者查询:

- 查询区间第k大

- 查询某个数的排名

- 查询整体第k大

最后问三种查询的结果之和。

题目分析:

首先对数进行离散化

然后对数字建立主席树,第k大的做法详见我的主席树学习第一弹

查询某个数的排名,树状数组直接做就好了,记录每个点是否出现过,然后找到sum(x)就是前缀一共有多少个数,也就是当前数的排名。

AC代码:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#define MAX 200007

using namespace std;

typedef long long LL;

int root[MAX],cnt_trees,n,len,h[MAX],hcnt;
LL ans1,ans2,ans3;

struct Query
{
int f,s,t,k;
void init ( int a , int b  ,int c , int d )
{f=a,s=b,t=c,k=d;}
}q[MAX<<1];

struct Tree
{
int l,r;
int sum;
}tree[4000007];

void build ( int& u , int l , int r )
{
u = cnt_trees++;
tree[u].sum = 0;
if ( l == r ) return;
int mid = l+r>>1;
build ( tree[u].l , l , mid );
build ( tree[u].r , mid+1 , r );
}

void update ( int p , int& u , int l , int r , int x  )
{
u = cnt_trees++;
tree[u] = tree[p];
tree[u].sum++;
if ( l == r ) return;
int mid = l+r>>1;
if ( x > mid )
update ( tree[p].r , tree[u].r , mid+1 , r , x );
else
update ( tree[p].l , tree[u].l , l , mid , x );
}

int query ( int p , int u , int l , int r , int k )
{
int sum = tree[tree[u].l].sum - tree[tree[p].l].sum;
if ( l == r ) return l;
int mid = l+r>>1;
if ( sum >= k ) return query ( tree[p].l , tree[u].l , l , mid , k );
else return query ( tree[p].r , tree[u].r , mid+1 , r , k-sum );
}

int c[MAX<<1];

int lowbit ( int x )
{
return x&-x;
}

void add ( int x )
{
while ( x < hcnt )
{
c[x]++;
x += lowbit ( x );
}
}

int sum ( int x )
{
int ret = 0;
while ( x )
{
ret += c[x];
x -= lowbit ( x );
}
return ret;
}

char s[30];

int main ( )
{
int cc = 1;
while ( ~scanf ( "%d" , &n ) )
{
cnt_trees = 0;
len = hcnt = 1;
memset ( c , 0 , sizeof ( c ) );
for ( int i = 1 ; i <= n ; i++ )
{
int x,y,z;
scanf ( "%s" , s );
if ( s[0] == 'I' )
{
q[i].f = 0;
scanf ( "%d" , &q[i].k );
h[hcnt++] = q[i].k;
}
else
{
int id = s[6]-48;
if ( id == 1 )
scanf ( "%d%d%d" , &x , &y , &z );
else
scanf ( "%d" , &z );
q[i].init ( id , x , y , z );
}
}
sort ( h+1 , h+hcnt );
build ( root[0] , 1 , hcnt-1 );
ans1 = ans2 = ans3 = 0;
for ( int i = 1 ; i <= n ; i++ )
{
if ( q[i].f == 0 )
{
int x = lower_bound ( h , h+hcnt , q[i].k )-h;
update ( root[len-1] , root[len] , 1 , hcnt-1 , x );
add ( x );
len++;
}
else if ( q[i].f == 1 )
ans1 += h[query ( root[q[i].s-1] , root[q[i].t] , 1 , hcnt-1 , q[i].k )];
else if ( q[i].f == 2 )
{
int x = lower_bound ( h , h+hcnt , q[i].k )-h;
ans2 += sum(x);
}
else if ( q[i].f == 3 )
ans3 += h[query ( root[0] , root[len-1] , 1 , hcnt-1 , q[i].k )];
}
printf ( "Case %d:\n" , cc++ );
printf ( "%I64d\n%I64d\n%I64d\n" , ans1 , ans2 , ans3 );
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  树状数组 主席树