1.HDU 1166  http://acm.hdu.edu.cn/showproblem.php?pid=1166

题目大意:
了解地方的兵营人数,每次询问告知区间内的总人数,其中会有兵营人数变更的更新操作

这里要用到求和的query:

int query(int x,int y)
{

    int
i=D+x-1,j=D+y+1,ans=0;
    for
(;i^j^1;i>>=1,j>>=1){
        if
(~i&1) ans+=tree[i^1];
        if
(j&1) ans+=tree[j^1];
    }

    return
ans;
}

代码如下:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <string>
 5 using namespace std;
 6 
 7 #define N 50005
 8 
 9 int a[N],tree[200010];
10 int D;
11 string s;
12 
13 void update(int x)
14 {
15     for(int i=x;i^1;i>>=1){
16         tree[i>>1]=tree[i]+tree[i^1];
17     }
18 }
19 
20 int query(int x,int y)
21 {
22     int i=D+x-1,j=D+y+1,ans=0;
23     for(;i^j^1;i>>=1,j>>=1){
24         if(~i&1) ans+=tree[i^1];
25         if(j&1) ans+=tree[j^1];
26     }
27     return ans;
28 }
29 int main()
30 {
31     int T,n,c,d;
32     cin>>T;
33     for(int i=1;i<=T;i++){
34         D=1;
35         memset(tree,0,sizeof(tree));
36         scanf("%d",&n);
37         for(int j=1;j<=n;j++) scanf("%d",&a[j]);
38         while(D<n+2) D<<=1;
39         for(int j=1;j<=n;j++) tree[D+j]=a[j];
40         for(int j=D-1;j>=1;j--) tree[j]=tree[j<<1]+tree[j<<1|1];
41         printf("Case %d:\n",i);
42         while(cin>>s){
43             if(s=="End") break;
44 
45             else if(s=="Add"){
46                 scanf("%d%d",&c,&d);
47                 tree[D+c]+=d;
48                 update(D+c);
49             }
50             else if(s=="Sub"){
51                 scanf("%d%d",&c,&d);
52                 tree[D+c]-=d;
53                 update(D+c);
54             }
55             else if(s=="Query"){
56                 scanf("%d%d",&c,&d);
57                 printf("%d\n",query(c,d));
58             }
59         }
60     }
61     return 0;
62 }
View Code

 

2.HDU 1754 http://acm.hdu.edu.cn/showproblem.php?pid=1754

题目大意:
老师想要知道某段学生区间的最高分,中间涉及学生成绩的更新操作。

这里用到的是求最大值的query:
int query(int x,int y)
{

    int
i=D+x-1,j=D+y+1,ans=-1;
    for
(;i^j^1;i>>=1,j>>=1){
        if
(~i&1) ans=max(ans,tree[i^1]);
        if
(j&1)  ans=max(ans,tree[j^1]);
    }

    return
ans;
}

总代码如下:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 200010
int a[N],tree[4*N],D;

void init()
{
    D=1;
    memset(tree,-1,sizeof(tree));
}
void treeBuild()
{
    for(int i=D-1;i>=1;i--)
        tree[i]=max(tree[i<<1],tree[(i<<1)^1]);
}
void update(int i)
{
    for(;i^1;i>>=1){
        tree[i>>1]=max(tree[i],tree[i^1]);
    }
}
int query(int x,int y)
{
    int i=D+x-1,j=D+y+1,ans=-1;
    for(;i^j^1;i>>=1,j>>=1){
        if(~i&1) ans=max(ans,tree[i^1]);
        if(j&1)  ans=max(ans,tree[j^1]);
    }
    return ans;
}
int main()
{
    int n,m,x,y;
    char c;
    while(scanf("%d%d",&n,&m)!=EOF){
        init();
        while(D<n+2) D<<=1;
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            tree[D+i]=a[i];
        }
        treeBuild();
        for(int i=1;i<=m;i++)
        {
            cin>>c;
            if(c=='U'){
                scanf("%d%d",&x,&y);
                tree[D+x]=y,update(D+x);
            }
            else if(c=='Q'){
                scanf("%d%d",&x,&y);
                printf("%d\n",query(x,y));
            }
        }
    }
    return 0;
}
View Code

 

3.HDU 2795 http://acm.hdu.edu.cn/showproblem.php?pid=2795
题目大意:
不断将广告靠上,再靠左贴,问能够贴到的行数

这里我们在线段树上存储的是行的位置,用w[]数组存储每行还能存多少长度的广告

这里虽说高度能达到10^9,但是我们在规划线段树的长度时并不需要那么长,因为n最大为200000,我们规划线段树的底层取到的是min(n,h);

所以整棵树最大达到4*n即可

这里不断将能够达到最大值的位置放在树顶,

判断时不断往下,因为要贴广告时尽可能朝上,所以如果满足往左走,不满足往右走

query

int query(int k)
{

    int
t=1;
    if
(w[tree[t]]<k) return -1; while(t<D){ if(w[tree[t<<1]]>=k) t<<=1;
        else
t=t<<1|1;
    }

    return
t-D;
}

总代码如下:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 200010
int w[N],tree[4*N],D,h,m,n,x,Min;

void update(int i)
{
    for(;i^1;i>>=1)
        tree[i>>1]=w[tree[i]]>w[tree[i^1]]?tree[i]:tree[i^1];
}

int query(int k)
{
    int t=1;
    if(w[tree[t]]<k) return -1;
    while(t<D){
        if(w[tree[t<<1]]>=k) t<<=1;
        else t=t<<1|1;
    }
    return t-D;
}

int main()
{
    while(scanf("%d%d%d",&h,&m,&n)!=EOF){
        Min=min(h,n);
        memset(tree,0,sizeof(tree));
        w[0]=0;
        for(D=1;D<Min+2;D<<=1);
        for(int i=1;i<=Min;i++) w[i]=m,tree[D+i]=i;
        for(int i=D-1;i>=1;i--) tree[i]=w[tree[i<<1]]>w[tree[i<<1|1]]?tree[i<<1]:tree[i<<1|1];
        for(int i=1;i<=n;i++){
            scanf("%d",&x);
            int t=query(x);
            printf("%d\n",t);
            w[t]-=x,update(D+t);
        }
    }
    return 0;
}
View Code

 

 posted on 2014-07-30 14:35  Love风吟  阅读(226)  评论(0编辑  收藏  举报