zoukankan      html  css  js  c++  java
  • [POI2007]EGZ-Driving Exam

    能到达所有路的充要条件是能到达左右两端的路

    用vector反向建边对每条路左右分别求个最长不上升子序列

    预处理出每条路向左向右分别需要多建多少路才能到达最左端和最右端

    然后跑个(Theta(n))的尺取法就可以了

    本题最长不上升子序列用vector+zkw线段树比二分更加好想?

    原来标程的solve函数尺取时出锅(但是居然AC了

    感谢我自己回来看题解发现看不懂

    现在这题解是真题解了

    #include"cstdio"
    #include"cstring"
    #include"iostream"
    #include"algorithm"
    #include"vector"
    using namespace std;
    
    const int MAXN=1<<17;
    
    int n,m,P,K,np;
    int f[2][MAXN];
    int tree[MAXN<<1];
    struct rpg{bool kd;int h,fl,fr;};
    vector<rpg> vec[MAXN];
    
    int read()
    {
    	int x=0;char ch=getchar();
    	while(ch<'0'||'9'<ch) ch=getchar();
    	while('0'<=ch&&ch<='9') x=(x<<3)+(x<<1)+(ch^'0'),ch=getchar();
    	return x;
    }
    
    void calcl()
    {
    	for(int i=1;i<n;++i){
    		for(int j=0;j<vec[i].size();++j){
    			if(!vec[i][j].kd){
    				int l=MAXN+vec[i][j].h-1,r=MAXN+m+2,maxn=0;
    				while(l^r^1){
    					if(~l&1) maxn=max(maxn,tree[l^1]);
    					if(r&1) maxn=max(maxn,tree[r^1]);
    					l>>=1;r>>=1;
    				}vec[i][j].fl=maxn+1;
    			}
    		}for(int j=0;j<vec[i].size();++j){
    			if(!vec[i][j].kd){
    				for(int k=MAXN+vec[i][j].h;k;k>>=1){
    					tree[k]=max(tree[k],vec[i][j].fl);
    				}
    			}
    		}int l=MAXN,r=MAXN+m+2,maxn=0;
    		while(l^r^1){
    			if(~l&1) maxn=max(maxn,tree[l^1]);
    			if(r&1) maxn=max(maxn,tree[r&1]);
    			l>>=1,r>>=1;
    		}f[0][i+1]=maxn;
    	}return;
    }
    
    void calcr()
    {
    	for(int i=n;i>1;--i){
    		for(int j=0;j<vec[i].size();++j){
    			if(vec[i][j].kd){
    				int l=MAXN+vec[i][j].h-1,r=MAXN+m+2,maxn=0;
    				while(l^r^1){
    					if(~l&1) maxn=max(maxn,tree[l^1]);
    					if(r&1) maxn=max(maxn,tree[r^1]);
    					l>>=1;r>>=1;
    				}vec[i][j].fr=maxn+1;
    			}
    		}for(int j=0;j<vec[i].size();++j){
    			if(vec[i][j].kd){
    				for(int k=MAXN+vec[i][j].h;k;k>>=1){
    					tree[k]=max(tree[k],vec[i][j].fr);
    				}
    			}
    		}int l=MAXN,r=MAXN+m+2,maxn=0;
    		while(l^r^1){
    			if(~l&1) maxn=max(maxn,tree[l^1]);
    			if(r&1) maxn=max(maxn,tree[r&1]);
    			l>>=1,r>>=1;
    		}f[1][i-1]=maxn;
    	}return;
    }
    
    void init()
    {
    	n=read(),m=read(),P=read(),K=read();
    	for(int i=1;i<=P;++i){
    		int x=read(),y=read(),z=read();
    		if(z) vec[x].push_back((rpg){z^1,y+1});
    		else vec[x+1].push_back((rpg){z^1,y+1});
    	}calcl();memset(tree,0,sizeof(tree));calcr();
    	for(int i=1;i<=n;++i) f[0][i]=i-f[0][i]-1,f[1][i]=n-i-f[1][i];
    	return;
    }
    
    void solve()
    {
    	int ans=0,ct=0,cnt=0;
    	for(int i=1;i<=n;++i){
    		while(ct+1<=n&&f[1][i]+f[0][ct+1]<=K){
    			++ct;
    			if(!f[0][ct]&&!f[1][ct]) ++cnt;
    		}ans=max(ans,ct-i+1-cnt);
    		if(!f[0][i]&&!f[1][i]) --cnt;
    	}printf("%d
    ",ans);
    	return;
    }
    
    int main()
    {
    	init();
    	solve();
    	return 0;
    }
    
  • 相关阅读:
    20171121
    20171117
    20171106
    20171031
    20171024
    20170924
    20170721
    商品的分类
    会员价格的修改
    会员价格删除
  • 原文地址:https://www.cnblogs.com/AH2002/p/9620512.html
Copyright © 2011-2022 走看看