当前位置:编程学习 > C/C++ >>

HDOJ 4417 Super Mario 线段树 单点更新 成段查询

[cpp] 
//HDOJ 4417 Super Mario 线段树 转化为单点更新 成段查询 
 
/*
题意:查询区间内小于等于某数的数的总和
 
思路:离线查询,先记录所有的询问并排序,然后一边删一边查,查之前把不满足的删掉
      就转化为简单的单点更新,成段求和。
*/ 
 
#include<stdio.h> 
#include<string.h> 
#include<stdlib.h> 
 
#define lson rt<<1,l,mid 
#define rson rt<<1|1,mid+1,r 
#define N 100005 
 
int T,n,m,cnt,ca = 1; 
int sum[N<<2],ans[N]; 
 
struct Node{ 
    int x; 
    int id; 
}s[N]; 
 
struct node{ 
    int from; 
    int to; 
    int k; 
    int id; 
}q[N]; 
 
int cmp(const void *a,const void *b){ 
    return (*(Node *)b).x - (*(Node *)a).x; 

 
int cmp1(const void *a,const void *b){ 
    return (*(node *)b).k - (*(node *)a).k; 

 
void Pushup(int rt){ 
    sum[rt] = sum[rt<<1]+sum[rt<<1|1]; 

 
void Debug(int n){ 
    int i; 
    for(i = 1; i <= n; ++i) 
        printf("sum[%d] : %d\n",i,sum[i]); 

 
void Build(int rt,int l,int r){ 
    if(l == r){ 
        scanf("%d",&s[cnt].x); 
        s[cnt].id = cnt++; 
        sum[rt] = 1; 
        return ; 
    } 
    int mid = (l + r) >> 1; 
    Build(lson); 
    Build(rson); 
    Pushup(rt); 

 
void Update(int rt,int l,int r,int x,int c){ 
    if(l == r){ 
        sum[rt] += c; 
        return ; 
    } 
    int mid = (r + l) >> 1; 
    if(x <= mid) Update(lson,x,c); 
    else            Update(rson,x,c); 
    Pushup(rt); 

 
int Query(int rt,int l,int r,int L,int R){ 
    if(L <= l && R >= r){ 
        return sum[rt]; 
    } 
    int res = 0; 
    int mid = (l + r) >> 1; 
    if(L <= mid) res += Query(lson,L,R); 
    if(R > mid ) res += Query(rson,L,R); 
    return res; 

 
void Init(){ 
    int i; 
    cnt = 1; 
    scanf("%d %d",&n,&m); 
    Build(1,1,n); 
    qsort(s+1,n,sizeof(s[0]),cmp); 
    for(i = 1; i <= m; ++i){ 
        scanf("%d %d %d",&q[i].from,&q[i].to,&q[i].k); 
        q[i].id = i; 
    } 
    qsort(q+1,m,sizeof(q[0]),cmp1); 

 
void Solve(){ 
    int i,j = 1; 
    memset(ans,0,sizeof(ans)); 
    for(i = 1; i <= n; ++i){ 
        while(s[i].x <= q[j].k){ 
            ans[q[j].id] = Query(1,1,n,q[j].from+1,q[j].to+1); 
            ++j; 
            if(j > m)    break; 
        } 
        if(s[i].x > q[j].k){ 
            Update(1,1,n,s[i].id,-1);    
        } 
    } 

 
void Print(){ 
    int i; 
    printf("Case %d:\n",ca++); 
    for(i = 1; i <= m; ++i) 
        printf("%d\n",ans[i]); 

 
int main(){ 
    scanf("%d",&T); 
    while(T--){ 
        Init(); 
        Solve(); 
        Print(); 
    } 
    return 0; 

补充:软件开发 , C++ ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,