zoukankan      html  css  js  c++  java
  • Codeforces 1166

    1166 D

    题意

    我们说一个序列 (x) (长为 (n) )是 (m-cute) 的当且仅当 (x_i = x_{i - 1} + x_{i - 2} + dots + x_1 + r_i (1 le r_i le m)) 。现在给定 (x) 的首项和末项以及 (m) ,问是否存在合法的 (x) 。存在还需要构造一个。 ((x_1,x_n,mle 10^{14}))

    Example

    input
    2
    5 26 2
    3 9 1
    output
    4 5 6 13 26
    -1

    先假定所有的 (r_i=1) ,算出 (n) ,然后再从左往右一个个往上加

    Code

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=53;
    long long a[maxn],c[maxn],s,t,m;
    int n;
    void calcn(){
    	n=2;
    	long long sum=s;
    	a[1]=s;
    	while(1){
    		a[n]=sum+1;
    		if(a[n]>t)break;
    		sum+=a[n];
    		n++;
    	}
    	n--;
    }
    int main(){
    	int T;
    	scanf("%d",&T);
    	while(T--){
    		scanf("%lld%lld%lld",&s,&t,&m);
    		calcn();
    		for(int i=1;i<=n;i++)c[i]=0;
    		long long x=t-a[n],y,k;
    		for(int i=2;i<=n&&x>0;i++){
    			k=(i==n?1:1ll<<(n-i-1));
    			y=min(m-1,x/k);
    			x-=y*k;
    			c[i]+=y;
    		}
    		long long sum=s;
    		a[1]=s;
    		for(int i=2;i<=n;i++){
    			a[i]=sum+1+c[i];
    			sum+=a[i];
    		}
    		if(a[n]==t){
    			printf("%d ",n);
    			for(int i=1;i<=n;i++)printf("%lld ",a[i]);
    			puts("");
    		}
    		else puts("-1");
    	}
    	return 0;
    }
    

    1166 E

    题意

    (m) 个数(未知),有 (n) 天,一个人每天会选择这些数的一个子集 (D_i) ,该子集的补集记为 (S_i) ,现在要你是否存在这 (m) 个数,使得对于每个 (i)( ext{lcm}(D_i)> ext{lcm}(S_i))((nle 10^4,mle 50))

    Examples

    input
    2 5
    3 1 2 3
    3 3 4 5
    output
    possible
    input
    10 10
    1 1
    1 2
    1 3
    1 4
    1 5
    1 6
    1 7
    1 8
    1 9
    1 10
    output
    impossible

    反正法。
    假设 (exists i,j,D_i∩D_j=∅) ,那么有 (D_i⊆S_j,D_j⊆S_i) ,则 ( ext{lcm}(D_i)le ext{lcm}(S_j), ext{lcm}(D_j)le ext{lcm}(S_i)) 。所以 $$ ext{lcm}(D_j)> ext{lcm}(S_j)≥ ext{lcm}(D_i)> ext{lcm}(S_i)≥ ext{lcm}(D_j)$$
    矛盾,所以如果要possible就必须满足对于 (∀i,j,D_i∩D_j≠∅) 。也就是说任意两个 (D_i) 有交集。 (O(nm^2)) 暴力判断。

    1166 F

    题意

    一张图, (n) 个点 (m) 条边,现在有 (q) 个操作,有两种:

    • (x,y) 间连一条颜色为 (w) 的边。
    • 询问从 (x)(y) 是否存在彩虹路径。

    彩虹路径:
    对于该路径经过的所有的节点数组 (c) ,满足对于每个 (1le ile frac{k-1}{2}) ,满足边 ((c_{2i},c_{2i-1}))((c_{2i},c_{2i+1})) 颜色相同。

    Example

    input

    4 3 2 4
    1 2 1
    2 3 1
    3 4 2
    ? 1 4
    ? 4 1
    + 3 1 2
    ? 4 1
    

    output

    Yes
    No
    Yes
    

    显然最开始的 (m) 条边可以看成加边操作。
    新建一张图。对于原图节点 (x,y,z) ,如果 ((x,y))((x,z)) 颜色相同,那么新图中连边 ((y,z))
    所以对于询问,如果彩虹路径是经过偶数条边的,我们只需要判断两个节点在新图中是否处在同一个连通块内,用并查集维护。
    但如果经过奇数条边,最后一条边的颜色就是任意的。因此对于每个节点维护一个set,表示新图中有多少个连通块与之相邻。
    加边操作其实就是检查有没有两条相邻的且颜色相同的两条边,如果有,合并两个连通块。
    加边的时候为了快速找到有没有上述条件的边,对每个节点再维护一个map, (map[u][w]) 表示最新加入的与节点 (u) 相邻的、颜色为 (w) 的边。
    合并连通块时别忘更新set和map,要启发式合并。
    复杂度: (O(n log n + (m + q)log^2 n))

    Code

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=100003;
    struct edge{int to,next;}e[maxn<<2];
    int head[maxn],cnte;
    void add(int u,int v){e[++cnte].to=v,e[cnte].next=head[u],head[u]=cnte;}
    int n,m,c,Q,f[maxn],sz[maxn];
    vector<int> cc[maxn];
    map<int,int> mp[maxn];
    map<int,int>::iterator itmp;
    set<int> st[maxn];
    set<int>::iterator itst;
    int find(int x){return x!=f[x]?f[x]=find(f[x]):f[x];}
    void Union(int x,int y){int fx=find(x),fy=find(y);if(fx!=fy)f[fx]=fy;}
    void merge(int x,int y){
    	if(x==y)return;
    	if(sz[x]>sz[y])swap(x,y);
    	for(auto u:cc[x]){
    		itst=st[u].find(x);
    		if(itst!=st[u].end())st[u].erase(itst),st[u].insert(y);
    		for(int i=head[u];i;i=e[i].next){
    			int v=e[i].to;
    			itst=st[v].find(x);
    			if(itst!=st[v].end())st[v].erase(itst),st[v].insert(y);
    		}
    	}
    	cc[y].insert(cc[y].end(),cc[x].begin(),cc[x].end());
    	cc[x].clear();
    	sz[y]+=sz[x];
    	Union(x,y);
    }
    void addedge(int u,int v,int w){
    	add(u,v),add(v,u);
    	int fu=find(u),fv=find(v);
    	st[v].insert(fu),st[u].insert(fv);
    	itmp=mp[u].find(w);
    	if(itmp!=mp[u].end()){
    		int mpu=itmp->second;
    		merge(fv,find(mpu));
    	}
    	mp[u][w]=v;
    	itmp=mp[v].find(w);
    	if(itmp!=mp[v].end()){
    		int mpv=itmp->second;
    		merge(fu,find(mpv));
    	}
    	mp[v][w]=u;
    }
    bool query(int x,int y){
    	return st[y].count(find(x));
    }
    int main(){
    	scanf("%d%d%d%d",&n,&m,&c,&Q);
    	for(int i=1;i<=n;i++){
    		cc[i].push_back(i);
    		st[i].insert(i);
    		f[i]=i;
    		sz[i]=1;
    	}
    	for(int i=1;i<=m;i++){
    		int u,v,w;
    		scanf("%d%d%d",&u,&v,&w);
    		addedge(u,v,w);
    	}
    	char mo[2];
    	int x,y,z;
    	while(Q--){
    		scanf("%s%d%d",mo,&x,&y);
    		if(*mo=='+'){
    			scanf("%d",&z);
    			addedge(x,y,z);
    		}
    		else{
    			puts(query(x,y)?"Yes":"No");
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    Redis持久化
    Windows Phone中扩展WebBrowser使其支持绑定html内容
    使用MVVM-Sidekick开发Universal App(二)
    使用MVVM-Sidekick开发Universal App(一)
    在Windows Phone 8中使用Live Connect并保持登陆状态
    iOS 打印结构体
    CGAffineTransformMake 矩阵变换 的运算原理(转)
    二维码快速扫描工具
    微信小程序之wx.request:fail错误,真机预览请求无效问题解决,安卓,ios网络预览异常(转)
    UIView的setNeedsLayout, layoutIfNeeded 和 layoutSubviews 方法之间的关系解释(转)
  • 原文地址:https://www.cnblogs.com/BlogOfchc1234567890/p/11041686.html
Copyright © 2011-2022 走看看