• codeforces Avito Code Challenge 2018


    C - Useful Decomposition

    大致题意:一颗n个点的树,问能不能在树中找到若干个个简单路径,使得路径两两之间有且仅有一个公共点且没有公共边,能则输出任一方案。

    画一画就能发现如果有两个点的度数大于1则不行

    满足则以度数最多的点为所有路径起点dfs即可找到方案

    #include<bits/stdc++.h>
    #define rre(i,r,l) for(int i=(r);i>=(l);i--)
    #define re(i,l,r) for(int i=(l);i<=(r);i++)
    #define Clear(a,b) memset(a,b,sizeof(a))
    #define inout(x) printf("%d",(x))
    #define douin(x) scanf("%lf",&x)
    #define strin(x) scanf("%s",(x))
    #define op operator
    typedef unsigned long long ULL;
    typedef const int cint;
    typedef long long LL;
    using namespace std;
    template<typename Q>
    void inin(Q &x)
    {
    	x=0;int f=0;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=1;ch=getchar();}
    	while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    	x=f?-x:x;
    }
    int n,head[100010],Next[200020],zhi[200020],ed,du[100010];
    void add(int a,int b)
    {
    	Next[++ed]=head[a],head[a]=ed,zhi[ed]=b;
    	Next[++ed]=head[b],head[b]=ed,zhi[ed]=a;
    }
    bool ans=1;
    int da[100010],top;
    void dfs(int x,int fa)
    {
    	int ss=0;
    	for(int i=head[x];i;i=Next[i])if(zhi[i]!=fa)
    		dfs(zhi[i],x),ss++;
    	if(!ss)da[++top]=x;
    	if(ss>1)ans=0;
    }
    int main()
    {
    	inin(n);
    	re(i,2,n)
    	{
    		int aa,bb;
    		inin(aa),inin(bb);
    		add(aa,bb);du[aa]++,du[bb]++;
    	}
    	int Max=0,o,sum=0;
    	re(i,1,n)if(du[i]>2)sum++;
    	if(sum>1){cout<<"No";return 0;}
    	re(i,1,n)if(du[i]>Max)Max=du[i],o=i;
    	for(int i=head[o];i;i=Next[i])
    		dfs(zhi[i],o);
    	if(!ans)cout<<"No";
    	else 
    	{
    		cout<<"Yes
    ";
    		cout<<top<<"
    ";
    		re(i,1,top)printf("%d %d
    ",o,da[i]);
    	}
    	return 0;
    }
    

    D - Bookshelves

    大致题意:给出含n个正整数序列和k,把序列分为k段,求每段的和 的 按位与 的和的最大值是多少

    假设我们现在的任务是判断存不存在一个方案使答案(x)满足 (x)&((1<<temp)==1)

    那么久用(dp[i][j])表示把前i个数分为j段能否满足,转移则判断是否存在(0<p<i)(dp[p][j-1]==1)使得((sum_{q=p+1}^i q)) & ((1<<temp)==(1<<temp))

    按位temp从高到低判断即可,每次dp都在以前的高位dp基础上转移,复杂度(O(n^4))

    注意清空dp[i]!!!!

    #include<bits/stdc++.h>
    #define rre(i,r,l) for(int i=(r);i>=(l);i--)
    #define re(i,l,r) for(int i=(l);i<=(r);i++)
    #define Clear(a,b) memset(a,b,sizeof(a))
    #define inout(x) printf("%d",(x))
    #define douin(x) scanf("%lf",&x)
    #define strin(x) scanf("%s",(x))
    #define op operator
    typedef unsigned long long ULL;
    typedef const int cint;
    typedef long long LL;
    using namespace std;
    template<typename Q>
    void inin(Q &x)
    {
    	x=0;int f=0;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=1;ch=getchar();}
    	while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    	x=f?-x:x;
    }
    int n,k;
    LL a[55];
    LL he(int l,int r)
    {
    	LL ret=a[l];
    	re(i,l+1,r)ret+=a[i];
    	return ret;
    }
    LL dp[55][55],ff[55][55],hh[55][55];
    bool pd(LL x)
    {
    	re(i,0,n)re(j,0,k)dp[i][j]=ff[i][j];
    	re(i,1,n)
    	{
    		Clear(dp[i],0);
    		re(j,1,min(i,k))
    		{
    			re(p,j-1,i-1)
    				if((hh[p+1][i]&x)==x&&dp[p][j-1])dp[i][j]=1;
    		}
    	}
    	if(dp[n][k])re(i,0,n)re(j,0,k)ff[i][j]=dp[i][j];
    	return dp[n][k];
    }
    void dfs(LL x,LL temp)
    {
    	if(x<0){cout<<temp;return ;}
    	if(pd(temp|(1LL<<x)))temp|=(1LL<<x);
    	dfs(x-1,temp);
    }
    int main()
    {
    	inin(n),inin(k);
    	ff[0][0]=1;
    	re(i,1,n)inin(a[i]);
    	re(i,1,n)re(j,i,n)
    		hh[i][j]=he(i,j);
    	dfs(62,0);
    	return 0;
    }
    

    E - Addition on Segments

    大致题意:一个长度为n的初始全为0的序列,有q次区间加的操作(l_i,r_i,x_i),问是否存在这q次操作的子集使得执行这些操作后序列中的最大值为(i),从小到大输出满足(1<=i<=n)的所有(i)

    考虑序列中的每个元素,如果执行的k次操作都覆盖这个点,则这个点一定是序列中的一个最大值,那么我们可以用这k个操作加的k个数来做背包大小为n的01背包,得出最大值为x的方案数。

    把每个操作分为两个操作:加入(x_i),删除(x_i),从左到右计算每个元素的答案,加入一个数则在当前背包中反向循环一遍,删除则在当前背包中正向循环一遍。

    划重点,01背包的删除操作

    场上感觉方案数会爆炸,于是随机了一个模数来取模(就像一个hash),后来我试试不取模也过了,所以方案数不会很多?还是说随机数据没法卡?

    #include<bits/stdc++.h>
    #define rre(i,r,l) for(int i=(r);i>=(l);i--)
    #define re(i,l,r) for(int i=(l);i<=(r);i++)
    #define Clear(a,b) memset(a,b,sizeof(a))
    #define inout(x) printf("%d",(x))
    #define douin(x) scanf("%lf",&x)
    #define strin(x) scanf("%s",(x))
    #define op operator
    typedef unsigned long long ULL;
    typedef const int cint;
    typedef long long LL;
    using namespace std;
    template<typename Q>
    void inin(Q &x)
    {
    	x=0;int f=0;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=1;ch=getchar();}
    	while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    	x=f?-x:x;
    }
    int n,q;
    const int mod=1e9-rand()%2333;
    struct wocao
    {
    	int wei,x,opt;
    	bool op < (const wocao &rhs)const 
    	{
    		return wei<rhs.wei;
    	}
    }cz[20020];
    int ed;
    int ans[10010];
    bool sum[10010];
    void add(int x)
    {
    	rre(i,n,x)(ans[i]+=ans[i-x])%=mod;
    }
    void del(int x)
    {
    	re(i,x,n)ans[i]=(mod+ans[i]-ans[i-x])%mod;
    }
    int main()
    {
    	inin(n),inin(q);
    	re(i,1,q)
    	{
    		int l,r,x;
    		inin(l),inin(r),inin(x);
    		ed++;
    		cz[ed].wei=l,cz[ed].x=x,cz[ed].opt=1;
    		ed++;
    		cz[ed].wei=r+1,cz[ed].x=x,cz[ed].opt=-1;
    	}
    	sort(cz+1,cz+ed+1);
    	ans[0]=1;int now=1;
    	re(i,1,n)
    	{
    		while(cz[now].wei==i&&now<=ed)
    		{
    			if(cz[now].opt==1)add(cz[now].x);
    			else del(cz[now].x);
    			re(j,1,n)if(ans[j])sum[j]=1;
    			now++;
    		}
    	}
    	int ss=0;
    	re(i,1,n)if(sum[i])ss++;
    	cout<<ss<<"
    ";
    	re(i,1,n)if(sum[i])printf("%d ",i);
    	return 0;
    }
    
  • 相关阅读:
    Centos 卸载 MySQL
    Kafka体系架构、命令、Go案例
    Go 平滑重启(优雅重启)
    etcd集群数据迁移至新集群
    ubuntu 20.04使用TLSv1
    mybatis拦截器对SQL处理,数据权限逻辑控制
    java敏感字查找和替换
    SpringBoot自定义validation验证
    java使用druid解析器解析SQL语句
    国产数据库人大金仓 KingbaseES V8 R2 在 x86_64 Linux 安装过程
  • 原文地址:https://www.cnblogs.com/NoCEinVegetable/p/9100517.html
Copyright © 2020-2023  润新知