[CODEVS3032]摆放球 解题报告

这个题本来我是想练堆用的,结果堆没练出来,倒是练了练线段树。

此题属于那种看起来特别简单,一做起来做出翔的那种;交了六遍,对拍了N年才A。

主要需要注意的是这么几点:

1、节点保存什么信息?

题目中让求的是距离最大,但这玩意儿在线段树中不太好办;

我一开始想当然地写成了r-l式的距离,结果合并信息的时候呵呵了。

更好的做法是保存区间中连续一段空橱子的个数:①设置变量意义时一定要从易于理解和调试的角度出发。

显然,最长连续区间的左右端点也是需要保存的,因为我们需要用它来求出球该放在什么地方。但是!若一个区间的长度为0,它的左右端点应该是哪里?

2、②若[l,r]的长度为0,则令l=r+1,r=l-1.

为什么?看看在合并的时候我们做了什么?

设struct TS{int lmax,lR,rmax,rL,max,L,R}

if(tree[node<<1].lR=((l+r)>>1)+1){

tree[node].lmax+=tree[node<<1|1].lmax;

tree[node].lR=tree[node<<1|1].lR;

}

这时,若tree[node<<1|1].lmax=0会发生什么呢?

若设此时tree[node<<1|1].lR=(l+r)>>1的话,则

tree[node<<1].lR=(l+r)>>1.

是正确的。

所以。。就这样吧。

3、③三个变量中选择最大的哪个该怎么做?

很容易混乱。。

条理清晰?

把条件都完整的列出来!

if(a>=b&&a>=c){}

if(b>=a&&b>=c){}

if(c>=a&&c>=b){}

4、球该放在哪?

显然球应该放在最长的连续无球橱子区间中,但是。。具体在哪里呢?

设区间[L,R]为一个最长连续无球橱子区间,且L>1,R<N.

则显然④球应该放在L-1与R+1的中位数的位置,才能使球与L-1和R+1的距离的最小值最大。

即x=(L-1+R+1)>>1=(L+R)>>1.

5、⑤特殊区间

从1往右延伸的区间与从N往左延伸的区间,球在这里的距离长度就是区间长度!

6、记录的max?

这时我们发现一个很大很大的问题!就是节点中记录max,它不是那个最短距离,最短距离应该是max+1>>1!

也就是说,若果我们按max的大小比较,永远在max最大的前提下选择左边的那个,很可能会导致只比当前选出的max小1而其+1>>1与当前选出的max相同且在其右边的max被漏掉导致全盘皆输!

但是,如果我们不按max来选,是否可能导致当前选出的max比较小,使得之后合成的max比实际选出的max要小呢?也就是说一个max差了1不算,但两个差了2就不一样了啊!

但是我们突然发现了一个问题!max不会被合成,唯一与max有关的运算只是Cmp;合成是交给lmax和rmax的,而lmax和rmax又不需要Cmp!

于是。。在无数遍的WA与摸爬滚打之中,我们终于找到了正解的道路。。

#include<iostream>
using namespace std;
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
struct TS{
	int lmax,rmax,max,L,R,lR,rL;
}tree[800000];
int point[1000001];
#define root 1,1,N
#define lson node<<1,l,(l+r)>>1
#define rson node<<1|1,((l+r)>>1)+1,r
inline void update(int node,int l,int r,int x,int A){
	if(l==r)
		if(A)tree[node]=(TS){1,1,1,x-1,x+1,x+1,x-1};
		else tree[node]=(TS){0,0,0,r,l,l,r};
	else{
		int m=(l+r)>>1;
		if(x>m)update(rson,x,A);
		else update(lson,x,A);

		tree[node].lmax=tree[node<<1].lmax;
		if(tree[node<<1].lR==m+1){
			tree[node].lmax+=tree[node<<1|1].lmax;
			tree[node].lR=tree[node<<1|1].lR;
		}
		else tree[node].lR=tree[node<<1].lR;

		tree[node].rmax=tree[node<<1|1].rmax;
		if(tree[node<<1|1].rL==m){
			tree[node].rmax+=tree[node<<1].rmax;
			tree[node].rL=tree[node<<1].rL;
		}
		else tree[node].rL=tree[node<<1|1].rL;

		int tmp=tree[node<<1].rmax+tree[node<<1|1].lmax;
		if(tree[node<<1].max+1>>1>=tree[node<<1|1].max+1>>1&&tree[node<<1].max+1>>1>=tmp+1>>1){
			tree[node].max=tree[node<<1].max;
			tree[node].L=tree[node<<1].L;
			tree[node].R=tree[node<<1].R;
		}
		else
			if(tmp+1>>1>=tree[node<<1].max+1>>1&&tmp+1>>1>=tree[node<<1|1].max+1>>1){
				tree[node].max=tmp;
				tree[node].L=tree[node<<1].rL;
				tree[node].R=tree[node<<1|1].lR;
			}
			else{
				tree[node].max=tree[node<<1|1].max;
				tree[node].L=tree[node<<1|1].L;
				tree[node].R=tree[node<<1|1].R;
			}
	}
	//cout<<l<<","<<r<<":"<<tree[node].max<<"("<<tree[node].L<<"->"<<tree[node].R<<")"<<" "<<tree[node].lmax<<"("<<l<<"->"<<tree[node].lR<<")"<<" "<<tree[node].rmax<<"("<<tree[node].rL<<"<-"<<r<<")\n";
}
inline void build(int node,int l,int r){
	tree[node]=(TS){r-l+1,r-l+1,r-l+1,l-1,r+1,r+1,l-1};
	if(l!=r)build(lson),build(rson);
}
inline void out(int node,int l,int r){
	if(l!=r)out(lson),out(rson);
	else cout<<!tree[node].max;
}
int main(){
	freopen("CODEVS3032.in","r",stdin);
	//freopen("CODEVS3032.out","w",stdout);
	memset(tree,0,sizeof(tree));
	int N,M,flag,A,x,tot=0,l,m,r;
	scanf("%d%d",&N,&M);
	build(root);
	while(M--){
		scanf("%d%d",&flag,&A);
		if(flag-1)update(root,point[A],1);
		else{
			//cout<<tree[1].lmax<<" "<<(tree[1].max+1>>1)<<" "<<tree[1].rmax<<endl;
			if(tree[1].lmax>=tree[1].rmax&&tree[1].lmax>=tree[1].max+1>>1)x=1;
			else
				if(tree[1].max+1>>1>=tree[1].rmax&&tree[1].max+1>>1>=tree[1].lmax)x=(tree[1].L+tree[1].R)>>1;
				else x=N;
			printf("%d\n",x);
			update(root,x,0);
			point[A]=x;
		}/*
		cout<<flag<<" "<<A<<":";
		out(root);
		cout<<endl;*/
	}
}

⑦重要总结:不论是多么简单的题,一定要写对拍!这个题中一半的问题全是拍出来的!有很多题都是看似简单实则不易。

时间: 2024-08-03 08:44:32

[CODEVS3032]摆放球 解题报告的相关文章

zoj 2313 Chinese Girls&#39; Amusement 解题报告

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1313 题目意思:有 N 个人(编号依次为1~N)围成一个圆圈,要求求出最大的 K (1 ≤ K ≤ N/2),表示从编号为1的人开始,将球传递给他后一个人数起的第K个人,第K个人又传递给往后数的第K个人......要求这样传递下去,且每个人都有机会接到球.也就是不存在当未使得全部人都接到一次球的情况下,某个人接收到两次以上的球. 详细的解题报告在这里: http:/

济南-1030试题解题报告

By shenben 本解题报告解析均为100分解题思路. 上午 T1 题意:从1− n中找一些数乘起来使得答案是一个完全平方数,求这个完全平方数 最大可能是多少. 解析: 1.  质因数分解 2.  1->n用质因数指数的相加的形式将1*n累乘起来 3.  扫一遍指数为奇数的质因数都-1,偶数的不变 4.  快速幂乘一遍,同时取模 T2 题意:有n个数,随机选择一段区间,如果这段区间的所有数的平均值在[L,R]中则 你比较厉害.求你比较厉害的概率 解析:(暴力枚举 40分) 100分需要推式子

洛谷OJ P1126 机器人搬重物 解题报告

洛谷OJ P1126 机器人搬重物 解题报告 by MedalPluS [题目描述]    机器人移动学会(RMI)现在正尝试用机器人搬运物品.机器人的形状是一个直径1.6米的球.在试验阶段,机器人被用于在一个储藏室中搬运货物.储藏室是一个N*M的网格,有些格子为不可移动的障碍.机器人的中心总是在格点上,当然,机器人必须在最短的时间内把物品搬运到指定的地方.机器人接受的指令有:向前移动1步(Creep):向前移动2步(Walk):向前移动3步(Run):向左转(Left):向右转(Right).

解题报告——2018级2016第二学期第五周作业排座椅

解题报告--2018级2016第二学期第五周作业 F:排座椅 描述 上课的时候总会有一些同学和前后左右的人交头接耳,这是令小学班主任十分头疼的一件事情.不过,班主任小雪发现了一些有趣的现象,当同学们的座次确定下来 之后,只有有限的D对同学上课时会交头接耳.同学们在教室中坐成了M行N列,坐在第i行第j列的同学的位置是(i,j),为了方便同学们进出,在教室中设 置了K条横向的通道,L条纵向的通道.于是,聪明的小雪想到了一个办法,或许可以减少上课时学生交头接耳的问题:她打算重新摆放桌椅,改变同学们桌椅

openjudge 9277 堆木头的解题报告

openjudge 9277 堆木头的解题报告.DP-前缀和-优化.(重点).总时间限制: 1000ms 内存限制: 131072kB描述Daxinganling produces a lot of timber. Before loading onto trains, the timberjacks will place the logs to some place in the open air first. Looking from the sideway, the figure of a

CSU-ACM2014暑假集训基础组训练赛(1) 解题报告

•Problem A HDU 4450                 水题,签到题 水题..没啥好说的.给大家签到用的. 1 #include <cstdio> 2 int main(){ 3 int n,a,ans; 4 while(scanf("%d",&n),n){ 5 ans = 0; 6 for(int i = 0;i < n;i++){ 7 scanf("%d",&a); 8 ans += a*a; 9 } 10 pr

解题报告 之 POJ3057 Evacuation

解题报告 之 POJ3057 Evacuation Description Fires can be disastrous, especially when a fire breaks out in a room that is completely filled with people. Rooms usually have a couple of exits and emergency exits, but with everyone rushing out at the same time

hdu 1541 Stars 解题报告

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1541 题目意思:有 N 颗星星,每颗星星都有各自的等级.给出每颗星星的坐标(x, y),它的等级由所有比它低层(或者同层)的或者在它左手边的星星数决定.计算出每个等级(0 ~ n-1)的星星各有多少颗. 我只能说,题目换了一下就不会变通了,泪~~~~ 星星的分布是不是很像树状数组呢~~~没错,就是树状数组题来滴! 按照题目输入,当前星星与后面的星星没有关系.所以只要把 x 之前的横坐标加起来就可以了

【百度之星2014~初赛(第二轮)解题报告】Chess

声明 笔者最近意外的发现 笔者的个人网站http://tiankonguse.com/ 的很多文章被其它网站转载,但是转载时未声明文章来源或参考自 http://tiankonguse.com/ 网站,因此,笔者添加此条声明. 郑重声明:这篇记录<[百度之星2014~初赛(第二轮)解题报告]Chess>转载自 http://tiankonguse.com/ 的这条记录:http://tiankonguse.com/record/record.php?id=667 前言 最近要毕业了,有半年没做