线段树·P1247贪婪大陆
2017-09-26 19:41
281 查看
贪婪大陆
题目描述
人类被蚂蚁们逼到了 Greed Island 上的一个海湾。现在,小 FF 的后方是一望无际的大海, 前方是变异了的超 级蚂蚁。 小 FF 还有大好前程,他可不想命丧于此, 于是他派遣手下最后一批改造 SCV 布置地雷以阻挡蚂蚁们的进攻。小 FF 最后一道防线是一条长度为 N 的战壕, 小 FF 拥有无数多种地雷,而 SCV 每次 可以在[ L , R ]区间埋放同一种不同于之前已经埋放的地雷。 由于情况已经十万火急,小 FF 在某些时候可能会询问你在[ L' , R'] 区间内有多少种不同的地雷, 他希望你能尽快的给 予答复。
输入格式
第一行为两个整数 n 和 m; n 表示防线长度, m 表示 SCV 布雷次数及小 FF 询问 的次数总和。接下来有 m 行, 每行三个整数 Q,L , R; 若 Q=1 则表示 SCV 在[ L , R ]这段区间 布上一种地雷, 若 Q=2 则表示小 FF 询问当前[ L , R ]区间总共有多少种地雷。
输出格式
对于小 FF 的每次询问,输出一个答案(单独一行),表示当前区间地雷总数。
样例数据
input5 4 1 1 3 2 2 5 1 2 4 2 3 5
output
1 2
这个题目区间修改与查询,很明显是线段树的题。
显然这题不能用简单的区间累加求最大值。 那么这题到底怎么做呢emmmm,
错误的思路1:对地雷的区间累加求和 这个很显然是错的。
错误的思路2:对于每一个与地雷区间[L,R]有部分重叠就累加,因为显然这种时候这个区间的地雷数会加一。这个思路貌似非常的正确。然而执行的时候发现根本无法查询,如果要查询的区间属于两串树,恭喜你GG。
一开始我想到的就是思路2,然后就错了。
问了老师才明白其中的奥妙。这题要用逆向思维。既然处理区间内的地雷数很难处理,那么处理不在区间内的地雷数呢?区分以下左右思路就非常清晰了:在线操作,输入一组地雷的区间,对区间左侧所有区间(点)的 “右边存在地雷数”+1。对区间右侧所有区间(点)的“左边存在地雷数”+1。最后查询的时候只要搜索需要查的区间的左右端点 用总地雷数减去这两个数就能过了。
然而我一开始漏了一种情况,即这个区间是一个重合的点,即L=R,于是 ....青草池塘处处WA。
下面是两套代码:
//代码1
#include<bits/stdc++.h> using namespace std; int n,m,x,y,ans,ll,rr,sum; struct shu { int leftpoint,rightpoint; int lazyleft,lazyright; }tree[401000]; int read() { int num=0; char c=getchar(); for(;c<'0'||c>'9';c=getchar()); for(;c>='0'&&c<='9';c=getchar())num=num*10+c-'0'; return num; } void add(int left,int right,int temp) { if(x<=left&&y>=right) return; if(right<x) {tree[temp].rightpoint++;tree[temp].lazyright++;return;} if(left>y) {tree[temp].leftpoint++;tree[temp].lazyleft++;return;} if(left==right) return; tree[temp*2].rightpoint+=tree[temp].lazyright; tree[temp*2].lazyright+=tree[temp].lazyright; tree[temp*2+1].rightpoint+=tree[temp].lazyright; tree[temp*2+1].lazyright+=tree[temp].lazyright; tree[temp*2].leftpoint+=tree[temp].lazyleft; tree[temp*2].lazyleft+=tree[temp].lazyleft; tree[temp*2+1].leftpoint+=tree[temp].lazyleft; tree[temp*2+1].lazyleft+=tree[temp].lazyleft; tree[temp].lazyleft=0; tree[temp].lazyright=0; int mid; mid=(left+right)/2; add(left,mid,temp*2); add(mid+1,right,temp*2+1); return; } void find(int left,int right,int temp) { if(x>right||y<left) return; bool blag=false; if(x==left&&x==right) {ll=tree[temp].leftpoint;blag=true;} if(y==right&&y==left) {rr=tree[temp].rightpoint;blag=true;} if(blag) return; if(left>x&&right<y) return; tree[temp*2].rightpoint+=tree[temp].lazyright; tree[temp*2].lazyright+=tree[temp].lazyright; tree[temp*2+1].rightpoint+=tree[temp].lazyright; tree[temp*2+1].lazyright+=tree[temp].lazyright; tree[temp*2].leftpoint+=tree[temp].lazyleft; tree[temp*2].lazyleft+=tree[temp].lazyleft; tree[temp*2+1].leftpoint+=tree[temp].lazyleft; tree[temp*2+1].lazyleft+=tree[temp].lazyleft; tree[temp].lazyleft=0; tree[temp].lazyright=0; int mid; mid=(left+right)/2; find(left,mid,temp*2); find(mid+1,right,temp*2+1); return ; } int main() { n=read(); m=read(); memset(tree,0,sizeof(tree)); int hh; for(int i=1;i<=m;i++) { hh=read(),x=read(),y=read(); if (hh==1) { add(1,n,1);sum++; } if(hh==2) { find(1,n,1); printf("%d\n",sum-ll-rr); //printf("sum=%d ll=%d rr=%d\n",sum,ll,rr); } } return 0; }
//代码2
#include<bits/stdc++.h>
using namespace std; int n,m,x,y,ll,rr,sum=0; struct shu { int leftpoint,rightpoint,lazyleft,lazyright; }tree[401000]; int read() { int num=0; char c=getchar(); for(;c<'0'||c>'9';c=getchar()); for(;c>='0'&&c<='9';c=getchar())num=num*10+c-'0'; return num; } void add(int left,int right,int temp,int R) { if(x>right||y<left) return; if(x<=left&&y>=right) { if(R==0){tree[temp].rightpoint++;tree[temp].lazyright++;return;} if(R==1){tree[temp].leftpoint++;tree[temp].lazyleft++;return;} return; } tree[temp*2].rightpoint+=tree[temp].lazyright; tree[temp*2].lazyright+=tree[temp].lazyright; tree[temp*2+1].rightpoint+=tree[temp].lazyright; tree[temp*2+1].lazyright+=tree[temp].lazyright; tree[temp*2].leftpoint+=tree[temp].lazyleft; tree[temp*2].lazyleft+=tree[temp].lazyleft; tree[temp*2+1].leftpoint+=tree[temp].lazyleft; tree[temp*2+1].lazyleft+=tree[temp].lazyleft; tree[temp].lazyleft=0; tree[temp].lazyright=0; int mid=(left+right)/2; add(left,mid,temp*2,R); add(mid+1,right,temp*2+1,R); return; } void find(int left,int right,int temp,int R) { if(x>right||y<left) return; if(x==left&&y==right&&R==0) {ll=tree[temp].leftpoint;return;} if(x==left&&y==right&&R==1) {rr=tree[temp].rightpoint;return;} tree[temp*2].rightpoint+=tree[temp].lazyright; tree[temp*2].lazyright+=tree[temp].lazyright; tree[temp*2+1].rightpoint+=tree[temp].lazyright; tree[temp*2+1].lazyright+=tree[temp].lazyright; tree[temp*2].leftpoint+=tree[temp].lazyleft; tree[temp*2].lazyleft+=tree[temp].lazyleft; tree[temp*2+1].leftpoint+=tree[temp].lazyleft; tree[temp*2+1].lazyleft+=tree[temp].lazyleft; tree[temp].lazyleft=0; tree[temp].lazyright=0; int mid=(left+right)/2; find(left,mid,temp*2,R); find(mid+1,right,temp*2+1,R); return; } int main() { n=read(); m=read(); memset(tree,0,sizeof(tree)); int hh,xx,yy; for(int i=1;i<=m;i++) { hh=read();xx=read();yy=read(); if(hh==1) { sum++; x=1,y=xx-1; add(1,n,1,0); x=yy+1,y=n; add(1,n,1,1); } if(hh==2) { x=y=xx; find(1,n,1,0); x=y=yy; find(1,n,1,1); printf("%d\n",sum-ll-rr); //printf("%d %d %d\n\n",sum,ll,rr); } } return 0; }
相关文章推荐
- 线段树【p2706】贪婪大陆
- 线段树 洛谷P3932 浮游大陆的68号岛
- P2184 贪婪大陆
- P3932 浮游大陆的68号岛 【线段树】
- cogs 1008 贪婪大陆
- P3932 浮游大陆的68号岛 【线段树】
- Cogs 1008. 贪婪大陆(树状数组)
- AC日记——贪婪大陆 洛谷 P2184
- luogu P2184 贪婪大陆
- △贪婪大陆(不会)
- 中国最大动漫论坛 贪婪大陆 被【无耻小人】侵占!!!全体斑竹,会员遭封id毒手
- 洛谷 P2184 贪婪大陆( 树状数组的活用 )
- P2184 贪婪大陆
- luogu P2184 贪婪大陆
- 贪婪大陆
- 【学术篇】luogu2184贪婪大陆
- 贪婪大陆(cogs 1008)
- COGS1008. 贪婪大陆[树状数组 模型转换]
- 鹿丸父子关于爱情的睿智对话(转自贪婪大陆)
- [luoguP2184] 贪婪大陆(树状数组)