zoukankan      html  css  js  c++  java
  • A

    C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和他手下Tidy又开始忙乎了。A国在海岸线沿直线布置了N个工兵营地,Derek和Tidy的任务就是要监视这些工兵营地的活动情况。由于采取了某种先进的监测手段,所以每个工兵营地的人数C国都掌握的一清二楚,每个工兵营地的人数都有可能发生变动,可能增加或减少若干人手,但这些都逃不过C国的监视。
    中央情报局要研究敌人究竟演习什么战术,所以Tidy要随时向Derek汇报某一段连续的工兵营地一共有多少人,例如Derek问:“Tidy,马上汇报第3个营地到第10个营地共有多少人!”Tidy就要马上开始计算这一段的总人数并汇报。但敌兵营地的人数经常变动,而Derek每次询问的段都不一样,所以Tidy不得不每次都一个一个营地的去数,很快就精疲力尽了,Derek对Tidy的计算速度越来越不满:"你个死肥仔,算得这么慢,我炒你鱿鱼!”Tidy想:“你自己来算算看,这可真是一项累人的工作!我恨不得你炒我鱿鱼呢!”无奈之下,Tidy只好打电话向计算机专家Windbreaker求救,Windbreaker说:“死肥仔,叫你平时做多点acm题和看多点算法书,现在尝到苦果了吧!”Tidy说:"我知错了。。。"但Windbreaker已经挂掉电话了。Tidy很苦恼,这么算他真的会崩溃的,聪明的读者,你能写个程序帮他完成这项工作吗?不过如果你的程序效率不够高的话,Tidy还是会受到Derek的责骂的.

    Input第一行一个整数T,表示有T组数据。
    每组数据第一行一个正整数N(N<=50000),表示敌人有N个工兵营地,接下来有N个正整数,第i个正整数ai代表第i个工兵营地里开始时有ai个人(1<=ai<=50)。
    接下来每行有一条命令,命令有4种形式:
    (1) Add i j,i和j为正整数,表示第i个营地增加j个人(j不超过30)
    (2)Sub i j ,i和j为正整数,表示第i个营地减少j个人(j不超过30);
    (3)Query i j ,i和j为正整数,i<=j,表示询问第i到第j个营地的总人数;
    (4)End 表示结束,这条命令在每组数据最后出现;
    每组数据最多有40000条命令
    Output对第i组数据,首先输出“Case i:”和回车,
    对于每个Query询问,输出一个整数并回车,表示询问的段中的总人数,这个数保持在int以内。
    Sample Input

    1
    10
    1 2 3 4 5 6 7 8 9 10
    Query 1 3
    Add 3 6
    Query 2 7
    Sub 10 2
    Add 6 3
    Query 3 10
    End 

    Sample Output

    Case 1:
    6
    33
    59

    注意:

    1、在查询query函数中,里面两个判断条件之间没有关系,不要使用“else”来使他们联系在一起

    2、注意在点修改中只要查到了那个修改的点,修改完要加上“return”

    点修改用else,区间修改和区间查询不用else

    错的我绝望。。。。。。

    上代码:

      1 #include<stdio.h>
      2 #include<string.h>
      3 #include<iostream>
      4 #include<algorithm>
      5 #include<queue>
      6 #include<stack>
      7 #include<vector>
      8 using namespace std;
      9 #define lson l,m,rt<<1
     10 #define rson m+1,r,rt<<1|1
     11 const int INF=0x3f3f3f3f;
     12 const int maxn=50005;
     13 int sum[maxn<<2],add[maxn<<2];
     14 int v[maxn],n;
     15 void pushup(int root) //统计每个点下一级左右分支的和
     16 {
     17     sum[root]=sum[root<<1]+sum[root<<1|1];
     18 }
     19 void build(int l,int r,int root)
     20 {
     21     if(l==r)  //当l==r的是侯就代表树到达了底部,此时既可以对他赋值,其中l,r是
     22     {
     23         //代表这个位置存的值对应的区间
     24         scanf("%d",&sum[root]);
     25         return;
     26     }
     27     int mid=(l+r)>>1;
     28     build(l,mid,root<<1);
     29     build(mid+1,r,root<<1|1);
     30     pushup(root);
     31 }
     32 //点修改
     33 void update(int l,int p,int ll,int rr,int root)//这个l代表要修改的值
     34 {
     35     if(ll==rr)
     36     {
     37         sum[root]+=p;
     38         return; //这里没有加return
     39     }
     40     int mid=(ll+rr)>>1;
     41     //这里要判断一下,保证你递归的区间中包含这个要修改的点
     42     if(l<=mid) update(l,p,ll,mid,root<<1); //注意这里是<=,等于号
     43     else update(l,p,mid+1,rr,root<<1|1);
     44     pushup(root);//更新完子节点之后不要忘记更新父节点
     45 }
     46 //下推标记
     47 void pushdown(int root,int ln,int rn) //ln、rn为左右子树上数字的数量
     48 {
     49     if(add[root])
     50     {
     51         add[root<<1]+=add[root];
     52         add[root<<1|1]+=add[root];
     53         sum[root<<1]+=add[root]*ln;
     54         sum[root<<1|1]+=add[root]*rn;
     55         //消除父节点标记
     56         add[root]=0;
     57     }
     58 }
     59 //更新区间,本题不涉及
     60 void Update(int l,int r,int p,int ll,int rr,int root)
     61 {
     62     if(l<=ll && r<=rr) //满足这个条件就说明这个区间都在我们要修改的区间中
     63     {
     64         sum[root]+=(rr-ll+1)*p;
     65         add[root]+=p; //标记父节点,不能只更新父节点不更新子节点,要记录下来,一旦有机会就要更新
     66         return;
     67     }
     68     int mid=(ll+rr)>>1;
     69     pushdown(root,mid-ll+1,rr-mid);
     70     //这里要判断要递归的区间必须要和我们要修改的区间有交集
     71     if(l<=mid) Update(l,r,p,ll,mid,root<<1);
     72     if(rr>mid) Update(l,r,p,mid+1,rr,root<<1|1);
     73     pushup(root);
     74 }
     75 int query(int L,int R,int l,int r,int rt)
     76 {
     77 //    if(L<=l && R>=r)
     78 //    {
     79 //        return sum[rt];
     80 //    }
     81     if(L <= l && r <= R){
     82 
     83         return sum[rt];
     84 
     85     }
     86     int m=(l+r)>>1;
     87     //在查询之前要往下推标记,要不然可以有些区间没有及时更新
     88     //pushdown(rt,mid-l+1,r-mid);
     89     int ans=0;
     90 //    if(L<=m) ans+=query(L,R,lson);
     91 //    else if(R>m) ans+=query(L,R,rson);
     92 //    return ans;
     93     if(L <= m)
     94 
     95         ans += query(L,R,lson);
     96 
     97     if(R > m)   //上一个条件和下一个条件没有关系,所以这里不能用else
     98                 //找了半天<_>..............................................
     99         ans += query(L,R,rson);
    100 
    101     return ans;
    102 }
    103 int main()
    104 {
    105     int t,k=0,n;
    106     char e[15];
    107     char q[5][15]={
    108         "Query",
    109         "Add",
    110         "Sub",
    111         "End",
    112     };
    113     scanf("%d",&t);
    114     while(t--)
    115     {
    116         memset(sum,0,sizeof(sum));
    117         memset(add,0,sizeof(add));
    118         memset(v,0,sizeof(v));
    119         k++;
    120         printf("Case %d:
    ",k);
    121         scanf("%d",&n);
    122         build(1,n,1);
    123         while(1)
    124         {
    125             scanf("%s",e);
    126             if(strcmp(e,q[0])==0)
    127             {
    128                 int l,r;
    129                 scanf("%d%d",&l,&r);
    130                 int sum=query(l,r,1,n,1);  //这里的查询写错了
    131                 printf("%d
    ",sum);  //要查询的区间要写在前面,在那里查询写在后面T_T
    132             }
    133             else if(strcmp(e,q[1])==0)
    134             {
    135                 int l,r;
    136                 scanf("%d%d",&l,&r);
    137                 update(l,r,1,n,1);
    138             }
    139             else if(strcmp(e,q[2])==0)
    140             {
    141                 int l,r;
    142                 scanf("%d%d",&l,&r);
    143                 update(l,-r,1,n,1);
    144             }
    145             else if(strcmp(e,q[3])==0)
    146             {
    147                 break;
    148             }
    149         }
    150     }
    151     return 0;
    152 }
    View Code

     B - I Hate It

    很多学校流行一种比较的习惯。老师们很喜欢询问,从某某到某某当中,分数最高的是多少。
    这让很多学生很反感。

    不管你喜不喜欢,现在需要你做的是,就是按照老师的要求,写一个程序,模拟老师的询问。当然,老师有时候需要更新某位同学的成绩。

    Input本题目包含多组测试,请处理到文件结束。
    在每个测试的第一行,有两个正整数 N 和 M ( 0<N<=200000,0<M<5000 ),分别代表学生的数目和操作的数目。
    学生ID编号分别从1编到N。
    第二行包含N个整数,代表这N个学生的初始成绩,其中第i个数代表ID为i的学生的成绩。
    接下来有M行。每一行有一个字符 C (只取'Q'或'U') ,和两个正整数A,B。
    当C为'Q'的时候,表示这是一条询问操作,它询问ID从A到B(包括A,B)的学生当中,成绩最高的是多少。
    当C为'U'的时候,表示这是一条更新操作,要求把ID为A的学生的成绩更改为B。
    Output对于每一次询问操作,在一行里面输出最高成绩。Sample Input

    5 6
    1 2 3 4 5
    Q 1 5
    U 3 6
    Q 3 4
    Q 4 5
    U 2 9
    Q 1 5

    Sample Output

    5
    6
    5
    9
    
    
            
     

    Hint

    Huge input,the C function scanf() will work better than cin

    这一道题就是pushup函数改变了,因为要求的是最大值,所以我们在子节点父节点中存的也应该是我们最终的目标

    代码:

     1 #include<stdio.h>
     2 #include<string.h>
     3 #include<iostream>
     4 #include<algorithm>
     5 #include<queue>
     6 #include<stack>
     7 #include<vector>
     8 using namespace std;
     9 #define lson l,m,rt<<1
    10 #define rson m+1,r,rt<<1|1
    11 const int INF=0x3f3f3f3f;
    12 const int maxn=200005;
    13 int sum[maxn<<2],add[maxn<<2];
    14 void pushup(int rt)
    15 {
    16     sum[rt]=max(sum[rt<<1],sum[rt<<1|1]);
    17 }
    18 void build(int l,int r,int rt)
    19 {
    20     if(l==r)
    21     {
    22         scanf("%d",&sum[rt]);
    23         return;
    24     }
    25     int m=(l+r)>>1;
    26     build(l,m,rt<<1);
    27     build(m+1,r,rt<<1|1);
    28     pushup(rt);
    29 }
    30 void update(int pos,int c,int l,int r,int rt)
    31 {
    32     if(l==r)
    33     {
    34         sum[rt]=c;
    35         return;
    36     }
    37     int m=(l+r)>>1;
    38     if(pos<=m) update(pos,c,l,m,rt<<1);
    39     else update(pos,c,m+1,r,rt<<1|1);
    40     pushup(rt);
    41 }
    42 int query(int L,int R,int l,int r,int rt)
    43 {
    44     if(L<=l && R>=r)
    45     {
    46         return sum[rt];
    47     }
    48     int m=(l+r)>>1;
    49     int ans=0;
    50     if(L<=m) ans=max(ans,query(L,R,l,m,rt<<1));
    51     if(R>m) ans=max(ans,query(L,R,m+1,r,rt<<1|1));
    52     return ans;
    53 }
    54 int main()
    55 {
    56     int n,m;
    57     char e[5];
    58     while(~scanf("%d%d",&n,&m))
    59     {
    60         memset(sum,0,sizeof(sum));
    61         build(1,n,1);
    62         while(m--)
    63         {
    64             int x,y;
    65             scanf("%s",e);
    66             scanf("%d%d",&x,&y);
    67             if(e[0]=='Q')
    68             {
    69                 printf("%d
    ",query(x,y,1,n,1));
    70             }
    71             else if(e[0]=='U')
    72             {
    73                 update(x,y,1,n,1);
    74             }
    75         }
    76     }
    77     return 0;
    78 }
    View Code

     C - A Simple Problem with Integers

    You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to each number in a given interval. The other is to ask for the sum of numbers in a given interval.

    Input

    The first line contains two numbers N and Q. 1 ≤ N,Q ≤ 100000.
    The second line contains N numbers, the initial values of A1, A2, ... , AN. -1000000000 ≤ Ai ≤ 1000000000.
    Each of the next Q lines represents an operation.
    "C a b c" means adding c to each of Aa, Aa+1, ... , Ab. -10000 ≤ c ≤ 10000.
    "Q a b" means querying the sum of Aa, Aa+1, ... , Ab.

    Output

    You need to answer all Q commands in order. One answer in a line.

    Sample Input

    10 5
    1 2 3 4 5 6 7 8 9 10
    Q 4 4
    Q 1 10
    Q 2 4
    C 3 6 3
    Q 2 4
    

    Sample Output

    4
    55
    9
    15

    Hint

    The sums may exceed the range of 32-bit integers.

    本题是区间修改和上面两个不一样,区间修改就要使用到标记,其次有些人用的是结构体里面存有这个节点区间的左右边界

    而我使用的是再传参的时候把边界传给下一个节点,这两种方法都可以

    上代码:

     1 #include<stdio.h>
     2 #include<string.h>
     3 #include<iostream>
     4 #include<algorithm>
     5 #include<queue>
     6 #include<stack>
     7 #include<vector>
     8 using namespace std;
     9 #define lson l,m,rt<<1
    10 #define rson m+1,r,rt<<1|1
    11 const int INF=0x3f3f3f3f;
    12 const int maxn=200005;
    13 typedef long long ll;
    14 ll sum[maxn<<2],add[maxn<<2];
    15 void pushup(ll rt)
    16 {
    17     sum[rt]=sum[rt<<1]+sum[rt<<1|1];
    18 }
    19 void build(ll l,ll r,ll rt)
    20 {
    21     if(l==r)
    22     {
    23         scanf("%lld",&sum[rt]);
    24         return;
    25     }
    26     ll m=(l+r)>>1;
    27     build(l,m,rt<<1);
    28     build(m+1,r,rt<<1|1);
    29     pushup(rt);
    30 }
    31 void pushdown(ll rt,ll ln,ll rn)
    32 {
    33     if(add[rt])
    34     {
    35         add[rt<<1]+=add[rt];
    36         add[rt<<1|1]+=add[rt];
    37         sum[rt<<1]+=add[rt]*ln;
    38         sum[rt<<1|1]+=add[rt]*rn;
    39         add[rt]=0;
    40     }
    41 }
    42 void update(ll L,ll R,ll C,ll l,ll r,ll rt)
    43 {
    44     if(l>=L && r<=R)
    45     {
    46         sum[rt]+=(r-l+1)*C;  //不要忘了这里是+=
    47         add[rt]+=C;
    48         return;
    49     }
    50     ll m=(l+r)>>1;
    51     pushdown(rt,m-l+1,r-m);
    52     if(L<=m) update(L,R,C,l,m,rt<<1);
    53     if(R>m) update(L,R,C,m+1,r,rt<<1|1);
    54     pushup(rt);
    55 }
    56 ll query(ll L,ll R,ll l,ll r,ll rt)
    57 {
    58     if(L<=l && R>=r)
    59     {
    60         return sum[rt];
    61     }
    62     ll m=(l+r)>>1;
    63     pushdown(rt,m-l+1,r-m);
    64     ll ans=0;
    65     if(L<=m) ans+=query(L,R,l,m,rt<<1);
    66     if(R>m) ans+=query(L,R,m+1,r,rt<<1|1);
    67     return ans;
    68 }
    69 int main()
    70 {
    71     ll n,m;
    72     char e[5];
    73     scanf("%lld%lld",&n,&m);
    74     build(1,n,1);
    75     while(m--)
    76     {
    77         scanf("%s",e);
    78         if(e[0]=='Q')
    79         {
    80             ll x,y;
    81             scanf("%lld%lld",&x,&y);
    82             printf("%lld
    ",query(x,y,1,n,1));
    83         }
    84         else  if(e[0]=='C')
    85         {
    86             ll x,y,z;
    87             scanf("%lld%lld%lld",&x,&y,&z);
    88             update(x,y,z,1,n,1);
    89         }
    90     }
    91     return 0;
    92 }
    View Code
  • 相关阅读:
    第七次作业-正规式到正规文法与自动机
    第六次作业——正规文法与正规式
    作业5 词法分析程序的设计与实现
    作业4—文法和语言总结与梳理
    第三次作业
    第二次作业-语言和文法
    编译原理第一次作业
    记录在腾讯云上搭建Ubuntu服务器
    第八章总结--排序 数据结构课程终章
    第七章-查找
  • 原文地址:https://www.cnblogs.com/kongbursi-2292702937/p/10811118.html
Copyright © 2011-2022 走看看