HDU 5200 漂亮得像个女人的解法

线段树,TLE,各种。唉。。。。我真是笨死了。。。。

我用的线段树是记录左右区间最长连续棵数的。。。反正TLE

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
const int N=50050;
struct Q{
	int val,index;
}Que[N];
int SegT[N*4],L[N*4],R[N*4],C[N*4];
int TreeH[N];
int ans[N];
bool cmp(Q a,Q b){
	if(a.val<b.val) return true;
	return false;
}

void build(int l,int r,int rt){
	L[rt]=R[rt]=r-l+1;C[rt]=1;
	if(l==r){
		SegT[rt]=TreeH[l];
		return ;
	}
	int m=(l+r)>>1;
	build(l,m,rt<<1);
	build(m+1,r,rt<<1|1);
	SegT[rt]=max(SegT[rt<<1],SegT[rt<<1|1]);
}

void slove(int l,int r,int rt,int hv){
	if(l==r){
		return ;
	}
	int m=(l+r)>>1;
	if(hv>=SegT[rt<<1])
	L[rt<<1]=R[rt<<1]=C[rt<<1]=0;
	else
	slove(l,m,rt<<1,hv);
	if(hv>=SegT[rt<<1|1]) L[rt<<1|1]=R[rt<<1|1]=C[rt<<1|1]=0;
	else
	slove(m+1,r,rt<<1|1,hv);
	L[rt]=L[rt<<1],R[rt]=R[rt<<1|1];
	if(L[rt<<1]>=m-l+1) L[rt]+=L[rt<<1|1];
	if(R[rt<<1|1]>=r-m) R[rt]+=R[rt<<1];
	C[rt]=C[rt<<1]+C[rt<<1|1];
	if(R[rt<<1]&&L[rt<<1|1]&&C[rt]) C[rt]--;
}

void readint1(int i) {
    TreeH[i]=0;
    char ch;
    ch=getchar();
    while(!isdigit(ch))ch=getchar();
    while(isdigit(ch)){
        TreeH[i]=TreeH[i]*10+ch-‘0‘;
        ch=getchar();
    }
}

int readint2(){
    int x=0;
    char ch;
    ch=getchar();
    while(!isdigit(ch))ch=getchar();
    while(isdigit(ch)){
        x=x*10+ch-‘0‘;
        ch=getchar();
    }
    return x;
}

int main(){
	int n,q;
	while(scanf("%d%d",&n,&q)!=EOF){
		memset(ans,0,sizeof(int)*n);
		for(int i=1;i<=n;i++)
		readint1(i);
		build(1,n,1);
		for(int i=0;i<q;i++){
			Que[i].val=readint2();
			Que[i].index=i;
		}
		sort(Que,Que+q,cmp);
		for(int i=0;i<q;i++){
			if(Que[i].val>=SegT[1]){
				ans[Que[i].index]=0;
			}
			else{
				slove(1,n,1,Que[i].val);
				ans[Que[i].index]=C[1];
			}
		}
		for(int i =0;i<q;i++)
		printf("%d\n",ans[i]);
	}
	return 0;
}

  

这个是看了别人之后的解法,漂亮啊。。。

把树排序,把询问排序,都按高度。两个指针扫描,对于不高于询问高度的树,对其原本的位置,若左右均未砍去,则段数+1,若均砍去,则段数-1,除此外,段数不变。

再感叹一下,漂亮啊。。。。T_T

#include <iostream>
#include <cstdio>
#include <algorithm>

using namespace std;
const int N=50050;

struct TH{
	int height,index;
}Tree[N],Que[N];
bool vis[N];
int n,q,ans[N];
bool cmp(TH a,TH b){
	if(a.height<b.height) return true;
	return false;
}

void work(int &c,int index){
	if(index==0){
		if(vis[index+1]) c--;
	}
	else if(index==n-1){
		if(vis[index-1]) c--;
	}
	else{
		if(!vis[index+1]&&!vis[index-1]) c++;
		else if(vis[index+1]&&vis[index-1]){
			c--;
		}
	}
}

int main(){
	while(scanf("%d%d",&n,&q)!=EOF){
		for(int i=0;i<n;i++){
			scanf("%d",&Tree[i].height);
			Tree[i].index=i;
		}
		sort(Tree,Tree+n,cmp);
		for(int i=0;i<q;i++){
			scanf("%d",&Que[i].height);
			Que[i].index=i;
		}
		sort(Que,Que+q,cmp);
		memset(vis,false,sizeof(vis));
		int ct=0;
		int counts=1;
		for(int i=0;i<q;i++){
			for(;ct<n;ct++){
				if(Tree[ct].height>Que[i].height) break;
				vis[Tree[ct].index]=true;
				work(counts,Tree[ct].index);
			}
			ans[Que[i].index]=counts;
		}
		for(int i=0;i<q;i++)
		printf("%d\n",ans[i]);
	}
	return 0;
}

  

时间: 2024-10-13 20:47:50

HDU 5200 漂亮得像个女人的解法的相关文章

*HDU 1394 经典逆序数的四种解法

1.暴力 [代码]: 1 /*HDU1394暴力写法*/ 2 #include <iostream> 3 #include <string.h> 4 #include <stdio.h> 5 6 using namespace std; 7 8 int A[50005]; 9 int Low[50005],Up[50005]; 10 int main(){ 11 int n; 12 while(~scanf("%d",&n)){ 13 int

hdu 5200 Trees [ 排序 离线 2指针 ]

传送门 Trees Accepts: 156 Submissions: 533 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Problem Description Today CodeFamer is going to cut trees.There are N trees standing in a line. They are numbered from 1 to N. Th

Hdu 5200 Trees (离线线段树)

题目大意: 校门外栽满了不同高度的树,每一次询问是 如果砍掉所有高度不超过q的树,那么还有多少个连续的块. 思路分析: 记录左连续和   右连续和  用来维护区间的连续块的数量. 即 seg[num] = seg[num<<1]+seg[num<<1|1] ; 如果中间部分连起来  那么减一即可. #include <cstdio> #include <iostream> #include <cstring> #include <algor

HDU - 5200 - Trees (upper_bound)

Trees Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 205    Accepted Submission(s): 68 Problem Description Today CodeFamer is going to cut trees.There are N trees standing in a line. They are

HDU 1312 ----- Red and Black 入门搜索 DFS解法

HDU 1312 ----- Red and Black  入门搜索  http://acm.hdu.edu.cn/showproblem.php?pid=1312 /*HDU 1312 ----- Red and Black 入门搜索 */ #include <cstdio> int n, m; //n行m列 int cnt, startx, starty; char mapp[25][25]; /*找一个连通的区域里可以走的块*/ void dfs(int x, int y){ if (x

HDU 5406 CRB and Apple 花样费用流向解法

题意简化一下就是一个序列,找出两个最大不下降子序列使得他们的长度和最长. = =作为一个DP渣,状态设计大概也就到了dp[i][j]表示第一个人最后一次取到i,第二个人取到j这个地方了..怎么在可行复杂度内转移?不会啊望天.. 其实作为图论工作者第一反应是费用流,但是边数太多了没敢搞= = 然而其实费用流也是可以过的.(x, y)表示容量为x费用为y, 建图很简单,建源s和汇e,加一个点t限制从 源最多流量是2,也就是s->t(2, 0).将各个点拆掉限制只能取一次,x->x'(1, 1),容

HDU 4135 Co-prime(容斥:二进制解法)题解

题意:给出[a,b]区间内与n互质的个数 思路:如果n比较小,我们可以用欧拉函数解决,但是n有1e9.要求区间内互质,我们可以先求前缀内互质个数,即[1,b]内与n互质,求互质,可以转化为求不互质,也就是有除1的公因数.那么我们把n质因数分解,就能算出含某些公因数的不互质的个数.因为会重复,所以容斥解决.因为因数个数可能很多(随便算了一个20!> 2e18,所以质因数分解个数不会超过20个),我们可以用二进制来遍历解决. #include<set> #include<map>

hdu 5719 Arrange

1 /******************************************************* 2 题目: Arrange(hdu 5719) 3 链接: http://acm.hdu.edu.cn/showproblem.php?pid=5719 4 解法: 可以发现 A1=B1=C1,如果B1不等于C1无解. 5 如果Bi<Bi-1,那么Ai=Bi;如果Ci>Ci-1,那 6 么Ai=Ci;如果Bi=Bi-1 && Ci=Ci-1那么 Bi<=A

hdu 4927 Java大数

http://acm.hdu.edu.cn/showproblem.php?pid=4927 [解法]:最后的结果是C(n-1,0)*a[n] -C(n-1, 1) * a[n-1] ……C(n-1,n-1)*a[1].符号位一正一负交替. 因为n有3000 之大,算C(n,i) 时要用到大数. 诶  其实早就把公式推出来了,就是坑在Java语言不熟悉,在编译的时候总是出现这个 我们一直以为是语法错误,但是又发现有什么地方写错了,卡了几个小时,人都要抓狂了. 今天拿着后面过的代码跟第一个交的比较