zoukankan      html  css  js  c++  java
  • 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
    ",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
    ",ans[i]);
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    Oracle学习(一)SQL基础
    结构型设计模式(二)桥接模式
    dubbo学习(十)spring boot整合dubbo
    dubbo学习(九)dubbo监控中心
    结构型设计模式(一)适配器模式
    取石子游戏
    卡特兰数
    做题中踩过的坑。。。
    51Nod1130斯特林近似
    51Nod1089最长回文子串 V2(Manacher算法)
  • 原文地址:https://www.cnblogs.com/jie-dcai/p/4412633.html
Copyright © 2011-2022 走看看