UESTC Training for Data Structures——H

Problem  H

Problem Description

斯巴达克斯又要带领角斗士们对葛雷博的罗马军队进行新一轮攻击了。他早已查探到罗马军队在前方有很多堡垒,排成一条直线,并且每个堡垒有多少人也是知道的。在激烈的斗争中,某些堡垒可能会死去一些人,罗马也可能会派一些新的士兵来支援。斯巴达克斯想在战斗中随时知道某一段连续区间[L,R](从第L个堡垒到第R个堡垒)内一共有多少士兵,以决定是否要对这段堡垒实行猛攻,还想知道这段区间内人数最多的堡垒有多少人,以在不能猛攻的情况下对该堡垒实行重点打击。斯巴达克斯苦于军队里全是角斗士,大字不识几个,所以他想请聪明的程序员帮他完成这项工作,但是如果程序效率不高的话,会延误战机。你能胜任这项工作么?

Input

第一行一个整数T,表示有T组测试数据。
每组数据第一行一个整数N(N<=50000),表示罗马有N个堡垒,接下来该一行有N个整数,第i个整数ai代表第i个城堡的初始人数(1<=ai<=100)。
接下来输入一个整数M(M<=50000),表示接下来有M条命令。
接下来M行,每行有一条命令,命令有3种形式:
A i x   (1<=i<=N,1<=x<=100)
第i个堡垒新增了x个人。
D i x  (1<=i<=N,1<=x<=100)
第i个堡垒战死x个人。
(注意:如果x大于当前第i个堡垒的人数,说明情报有误,则不处理此次命令)
Q L R  (1<=L<=R<=N)
询问第L个到第R个城堡总共有多少士兵,士兵数最多的城堡有多少士兵

Output

对于每个询问,输出一行,包含两个整数sum max,sum表示该询问区间内总士兵数,max表示该询问区间内人数最多的堡垒里的人数,sum max用一个空格隔开

Sample Input

1
10
1 2 3 4 5 6 7 8 9 10
7
Q 1 5
A 1 5
Q 1 5
D 10 11
Q 10 10
D 10 9
Q 10 10

Sample Output

15 5
20 6
10 10
1 1

 

/*用线段树维护*/

#include<iostream>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<ctime>
#include<cstdlib>
#define N 50005
using namespace std;
struct data
{
    int be,en;  //覆盖的区域
    int left,right;  //左右儿子的编号
    int max,sum;
}tree[4*N];
int a[N],tot;
int MAX(int a,int b)
{
    return a>b?a:b;
}
void make_tree(int st,int en)  //建树
{
    int now=++tot;
    tree[now].be=st,tree[now].en=en;
    if(st==en) tree[now].max=tree[now].sum=a[st];
    else
    {
        int mid=(st+en)/2;
        tree[now].left=tot+1;
        make_tree(st,mid);
        tree[now].right=tot+1;
        make_tree(mid+1,en);
        tree[now].max=MAX(tree[tree[now].left].max,tree[tree[now].right].max);
        tree[now].sum=tree[tree[now].left].sum+tree[tree[now].right].sum;
    }
}
void del(int v,int m,int k)  //更新点 m 处的值
{
    if(tree[v].be==tree[v].en && tree[v].en==m)
    {
        if(tree[v].sum>=k) { tree[v].sum-=k; tree[v].max-=k; }
        return;
    }
    int mid=(tree[v].be+tree[v].en)/2;
    if(m<=mid) del(tree[v].left,m,k); else del(tree[v].right,m,k);
    tree[v].max=MAX(tree[tree[v].left].max,tree[tree[v].right].max);
    tree[v].sum=tree[tree[v].left].sum+tree[tree[v].right].sum;
}
int qumax(int v,int st,int en)   //取区间[st,en]的最大值
{
    if(st<=tree[v].be && en>=tree[v].en) return tree[v].max;
    int mid=(tree[v].be+tree[v].en)/2;
    if(en<=mid) return qumax(tree[v].left,st,en);
    if(st>mid) return qumax(tree[v].right,st,en);
    return MAX(qumax(tree[v].left,st,mid),qumax(tree[v].right,mid+1,en));
}
int qusum(int v,int st,int en)  //取区间[st,en] 的和
{
    if(st<=tree[v].be && en>=tree[v].en) return tree[v].sum;
    int mid=(tree[v].be+tree[v].en)/2;
    if(en<=mid) return qusum(tree[v].left,st,en);
    if(st>mid) return qusum(tree[v].right,st,en);
    return qusum(tree[v].left,st,mid)+qusum(tree[v].right,mid+1,en);
}
int main()
{
    int t,n,m;
    scanf("%d",&t);
    for(int ca=1;ca<=t;ca++)
    {
        memset(a,0,sizeof(a));
        memset(tree,0,sizeof(tree));
        tot=0;
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        make_tree(1,n);
        scanf("%d",&m); char s[10]; gets(s);
        for(int i=1;i<=m;i++)
        {
            char ch; int k,m;
            scanf("%c%d%d",&ch,&k,&m); gets(s);
            if(ch=='Q') printf("%d %d\n",qusum(1,k,m),qumax(1,k,m));
            else if(ch=='D') del(1,k,m);
            else if(ch=='A') del(1,k,-m);
        }
    }
    return 0;
}


 

你可能感兴趣的:(工作,测试,tree,input,output,Training)