A - 敌兵布阵 ——B - I Hate It——C - A Simple Problem with Integers(线段树)
中央情报局要研究敌人究竟演习什么战术,所以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:\n",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\n",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 }
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\n",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 }
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
本题是区间修改和上面两个不一样,区间修改就要使用到标记,其次有些人用的是结构体里面存有这个节点区间的左右边界
而我使用的是再传参的时候把边界传给下一个节点,这两种方法都可以
上代码:
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\n",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 }
A - 敌兵布阵 ——B - I Hate It——C - A Simple Problem with Integers(线段树)的更多相关文章
- HDU 1166 敌兵布阵 (树状数组)
题目链接 : http://acm.hdu.edu.cn/showproblem.php?pid=1166 敌兵布阵 Time Limit: 2000/1000 MS (Java/Others) ...
- HDU 1166 敌兵布阵(分块)
敌兵布阵 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submi ...
- HDU 1166 敌兵布阵(线段树单点更新)
敌兵布阵 单点更新和区间更新还是有一些区别的,应该注意! [题目链接]敌兵布阵 [题目类型]线段树单点更新 &题意: 第一行一个整数T,表示有T组数据. 每组数据第一行一个正整数N(N< ...
- hdu acm 1166 敌兵布阵 (线段树)
敌兵布阵 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submi ...
- HDU 1166 敌兵布阵
B - 敌兵布阵 Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u Submit Sta ...
- HDU 1166 敌兵布阵(线段树模板题)
题目链接: 传送门 敌兵布阵 Time Limit: 2000MS Memory Limit: 32768 K Description C国的死对头A国这段时间正在进行军事演习,所以C国间谍头 ...
- ACM: 敌兵布阵 解题报告 -线段树
敌兵布阵 Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u Description Li ...
- hdu 敌兵布阵(线段树之单点更新)
敌兵布阵 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submi ...
- hdu 1166 敌兵布阵--BIT
BIT模版题,学完直接刷毫无压力,水的不要不要的 敌兵布阵 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Ja ...
随机推荐
- 【Spring Boot】创建一个简单的Spring Boot的 Demo
走进Spring Boot 文章目录 走进Spring Boot 环境搭建 新建Spring Boot项目 开始创建项目 配置JDK版本 和 Initializr Service URL 配置Proj ...
- 容器编排系统K8s之包管理器helm基础使用(二)
前文我们介绍了helm的相关术语和使用helm安装和卸载应用,回顾请参考:https://www.cnblogs.com/qiuhom-1874/p/14305902.html:今天我们来介绍下自定义 ...
- 二十五:XSS跨站值原理分类及攻击手法
HTML DOM树 XSS跨站产生原理,危害,特点 本质,产生层面,函数类,漏洞操作对应层,危害影响,浏览器内核版本 XSS是什么? XSS全称跨站脚本(Cross Site Scripting),为 ...
- 面试常问的ArrayQueue底层实现
public class ArrayQueue<T> extends AbstractList<T>{ //定义必要的属性,容量.数组.头指针.尾指针 private int ...
- MAX232数据方向
在调试一个新板子的时候,串口调试从来都是放在前面的,而由于是一个新板子,电路图也是新的,因此有时候不知道串口线结对了没有,这个时候可能会对照PCB和原理图去看一下,但有时候看的人会很迷糊,因为不同的人 ...
- Vue基础之Vue的模板语法
Vue基础之Vue的模板语法 数据绑定 01 数据绑定最常见的形式就是使用插值表达式(两个大括号!)[也就是小胡子语法!mustache] <body> <!-- Vue.js的应用 ...
- axios用法
1 axios.get('https://api.apiopen.top/getJoke?type=all', { 2 params: {//用于传参 3 type: 'all' 4 } 5 }).t ...
- 有状态 无状态 stateful stateless monolithic architecture microservice architecture 单体架构
为什么游戏公司的server不愿意微服务化? - 知乎 https://www.zhihu.com/question/359630395 我大概说了,方便测试,方便维护,方便升级,服务之间松耦合,可多 ...
- linux系统层面调优
linux系统层面调优和常见的面试题 - 云+社区 - 腾讯云 https://cloud.tencent.com/developer/article/1664287
- 题解【CF1444A Division】
题面 t 组数据. 给定参数 p,q,求一个最大的 x,满足 \((x|p)∧(q∤x)\). \(1\le t \le 500\),\(1\le p \le10^{18}\),\(2\le q\le ...