zoukankan      html  css  js  c++  java
  • STR[#6]

    photo

    小明在旅游的路上看到了一条美丽的河,河上有许多船只,有的船只向左航行,有的船只向右航行。小明希望拍下这一美丽的风景,并且把尽可能多的船只都完整地拍到一张照片中。

    小明位于河的边上,并且可以在河边的任意位置进行拍照,照相机的视野恰好为(90)度角,只能以垂直于河边的方向进行拍照。河上的船只全都可看作是平行于河边的一条线段,有的正在向左移动,有的正在向右移动,但移动速度恰好都是一样的。

    小明可以等待恰当的时间让尽量多的船只都走进照相机的视野里,你不需要考虑船只之间会互相遮挡视野的情况。

    首先,只用枚举能看到船沿的观察者(收缩法)

    然后,处理出所有观察者的位置。看左右两个观察者能否合并在一起即可。

    #include <cstdio>
    #include <algorithm>
    using namespace std;
    
    const int maxn=2e5+5;
    int n, cl, cr; //m[0/1]:向左/右的差分标记 p:观察者位置
    struct mark{ 
    	int pos, v; 
    	mark(int x=0, int y=0){ pos=x; v=y; }
    }m[2][maxn];
    bool cmp(const mark &a, const mark &b){ return a.pos<b.pos; }
    int p[maxn], cntp, l[maxn], r[maxn], a[maxn]; //l/r:这个观察者能看到多少个往左/往右的
    int main(){
    	scanf("%d", &n); int x, y, z, d;
    	for (int i=1; i<=n; ++i){
    		scanf("%d%d%d%d", &x, &y, &z, &d);
    		if (y-x>2*z) continue;  //直接忽略不可能看见的船
    		p[cntp++]=x+z; p[cntp++]=y-z;  //观察者的可能位置
    		//在此区域内的观察者能看到向0/1行驶的这艘船
    		if (d==-1){ m[0][cl++]=mark(y-z, 1), m[0][cl++]=mark(x+z+1, -1); } 
    		else{ m[1][cr++]=mark(y-z, 1), m[1][cr++]=mark(x+z+1, -1); } 
    	}
    	sort(p, p+cntp); sort(m[0], m[0]+cl, cmp); sort(m[1], m[1]+cr, cmp); 
    	int t=0, now=0;
    	for (int i=0; i<cntp; ++i){  //当前观察者能看到几艘向左的船
    		while (m[0][t].pos<=p[i]&&t<cl) now+=m[0][t++].v;
    		l[i]=now; }
    	t=0; now=0;
    	for (int i=0; i<cntp; ++i){  //当前观察者能看到几艘向右的船
    		while (m[1][t].pos<=p[i]&&t<cr) now+=m[1][t++].v;
    		r[i]=now; }
    	a[0]=r[0]; int ans=0;  //a表示前缀最大值
    	for (int i=1; i<cntp; ++i) a[i]=max(a[i-1], r[i]);
    	//for (int i=0; i<cntp; ++i) printf("%d
    ", a[i]);
    	for (int i=1; i<cntp; ++i) ans=max(ans, l[i]+a[i-1]);  //左右合成
    	printf("%d
    ", ans);
    	return 0;
    }
    

    graph

    有一张无自环无重边的无向图,求有多少个边集,使得删掉边集里的边后,图里恰好有K个连通块。

    (f[S][j]),表示S集合分成j个连通块有多少种边集。为了去重,锁定一个点p,设(S_psubset S,p in S_p),那么(f[S][j]+=f[S-S_p][j-1]*f[S_p][1])

    #include <cstdio>
    using namespace std;
    #define popc __builtin_popcount
    #define lowbit __builtin_ctz
    
    typedef long long LL;
    const int maxn=15, mod=1e9+9;
    int n, m, k, pw2[maxn*maxn], G[maxn][maxn], in[1<<maxn];
    LL f[1<<maxn][maxn];
    int main(){
    	pw2[0]=1;
    	for (int i=1; i<maxn*maxn; ++i) pw2[i]=pw2[i-1]*2%mod;
    	scanf("%d%d%d", &n, &m, &k); int x, y, v;
    	for (int i=1; i<=m; ++i){
    		scanf("%d%d", &x, &y); --x; --y; G[x][y]=G[y][x]=1; }
    	for (int i=1; i<1<<n; ++i) if (popc(i)>1){
    		v=lowbit(i);
    		in[i]=in[i^(1<<v)];
    		for (int j=0; j<n; ++j)
    			if (G[v][j]&&(i&(1<<j))) ++in[i];
    		//printf("%d %d %d %d
    ", i, v, in[i^(1<<v)], in[i]);
    	}
    	for (int i=1; i<1<<n; ++i) if (popc(i)>1){
    		f[i][1]=pw2[in[i]];
    		for (int j=popc(i); j>1; --j){  //切成几个连通块
    			int v=lowbit(i), k=i^(1<<v), r=i^(1<<v);
    			do{  //枚举子连通块
    				f[i][j]=(f[i][j]+f[1<<v|k][1]*f[r^k][j-1])%mod;
    				k=k-1&r;
    			}while(k!=r);
    			f[i][1]-=f[i][j];
    		} 
    		f[i][1]=f[i][1]%mod+(f[i][1]>>63&mod);
    	} else f[i][1]=1;
    	printf("%lld
    ", f[(1<<n)-1][k]);
    	return 0;
    }
    
  • 相关阅读:
    Hadoop面试
    Node.js面试题
    Node.js面试题
    [转载]最好的关系,是我懂你的不容易
    据说练就了一指禅神功的觅闻实时手机新闻网,正以每天2000+IP的用户量递增。有智能手机的可以当场进行体验,没有的就算了哈
    刚6瓶啤酒4两56度白酒下肚,居然20分钟做了一手机版网站 !
    Android:刚6瓶啤酒4两56度白酒下肚,居然20分钟做了一手机版网站 !
    IT人生的价值和意义 感觉真的有了
    (Android+IOS)正在做一个新闻App,做的差不多了,听听大家的建议 (图)
    (Android 即时通讯) [悬赏],无论是谁发现一个漏洞奖励人民币1000元!
  • 原文地址:https://www.cnblogs.com/MyNameIsPc/p/9662906.html
Copyright © 2011-2022 走看看