zoukankan      html  css  js  c++  java
  • Codeforces Round #639 (Div. 2)

    前情提要

    这个博客好像已经停更两个月了呢。
    这段时间就算是摸鱼了吧...
    在两周前刚刚比完校赛,我们队终于以rank#8,rank#9,rank#10的成绩获得了暑期集训的资格。
    队名也由之前随便起的Avengers,Prevengers改成了Die_Java
    队伍的wiki也搬家搬到了这里
    这段时间,知识点该不会啥还是不会啥,但是每周日的训练赛还是打的。
    总之爷又回来了!!!

    A. Puzzle Pieces

    题解

    全摆一行显然可以,一横一竖这么交替摆就行,考虑两行的话,那个很讨厌的凹槽画画图就能发现,只有2*2才能满足,除了这两类剩下的都不行。

    #include<bits/stdc++.h>
    using namespace std;
    #define mem(a,b) memset(a,b,sizeof(a))
    typedef long long LL;
    typedef pair<int,int> PII;
    #define X first
    #define Y second
    inline int read()
    {
    	int x=0,f=1;char c=getchar();
    	while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
    	while(isdigit(c)){x=x*10+c-'0';c=getchar();}
    	return x*f;
    }
    int T,n,m;
    int main()
    {
    	T=read();
    	while(T--)
    	{
    		n=read();m=read();
    		if(n>m)swap(n,m);
    		if(n==1)printf("YES
    ");
    		else if(n==2 && m==2)printf("YES
    ");
    		else printf("NO
    "); 
    	}
    	return 0;
    }
    

    B. Card Constructions

    题解

    先来一个小学级别的递推:(f_i=f_{i-1}+3*i-1),然后就根据题意不断二分就好了

    #include<bits/stdc++.h>
    using namespace std;
    #define mem(a,b) memset(a,b,sizeof(a))
    typedef long long LL;
    typedef pair<int,int> PII;
    #define X first
    #define Y second
    inline int read()
    {
    	int x=0,f=1;char c=getchar();
    	while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
    	while(isdigit(c)){x=x*10+c-'0';c=getchar();}
    	return x*f;
    }
    int T,n;
    LL f[50010];
    int func(int x)
    {
    	if(x<=0)return 0;
    	int pos=lower_bound(f+1,f+50000+1,x)-f;
    	if(f[pos]==x)return 1;
    	if(f[pos-1]==0)return 0;	
    	return 1+func(x-f[pos-1]);
    }
    int main()
    {	
    	f[1]=2;
    	for(int i=2;i<=50000;i++)f[i]=f[i-1]+3ll*i-1ll;
    	T=read();
    	while(T--)
    	{
    		n=read();
    		printf("%d
    ",func(n));
    	}
    	return 0;
    }
    

    C. Hilbert's Hotel

    题解

    经典希尔伯特酒店。(当时没发现这个标题是这个意思,导致读题卡了半天)
    有冲突的意思,翻译一下就是(a_i-a_j equiv i-j(mod N)),进一步写(a_i-a_j=k*N+i-j),移项(a_i+i equiv a_j+j (mod N)),开个vis数组记录一下即可,注意要把负数给加成正数。

    #include<bits/stdc++.h>
    using namespace std;
    #define mem(a,b) memset(a,b,sizeof(a))
    typedef long long LL;
    typedef pair<int,int> PII;
    #define X first
    #define Y second
    inline int read()
    {
    	int x=0,f=1;char c=getchar();
    	while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
    	while(isdigit(c)){x=x*10+c-'0';c=getchar();}
    	return x*f;
    }
    const int maxn=200010;
    int T,n,a;
    bool vis[maxn];
    int main()
    {
    	T=read();
    	while(T--)
    	{
    		n=read();
    		bool ok=0;
    		for(int i=0;i<n;i++)vis[i]=0;
    		for(int i=1;i<=n;i++)
    		{
    			a=(read()+i+(1000000000)/n*n+n)%n;
    			if(vis[a]==1 && !ok){
    				printf("NO
    ");
    				ok=1;
    			} 
    			vis[a]=1;
    		} 
    		if(!ok)printf("YES
    ");
    	} 
    	return 0;
    }
    

    D. Monopole Magnets

    题解

    结论题
    最终答案就是四连块数量。
    判无解的情况多点儿,
    第一点是:黑色块不能有凹进去的部分,因为如果有凹进去部分的话一定会被吸到白色区域。
    第二点,在本行本列都没有黑格的地方是可以放北极磁铁的,因为不会有影响,其他地方北极磁铁必须放到黑格。
    代码可读性极差,自己都不知道自己在写啥

    #include<bits/stdc++.h>
    using namespace std;
    #define mem(a,b) memset(a,b,sizeof(a))
    typedef long long LL;
    typedef pair<int,int> PII;
    #define X first
    #define Y second
    inline int read()
    {
    	int x=0,f=1;char c=getchar();
    	while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
    	while(isdigit(c)){x=x*10+c-'0';c=getchar();}
    	return x*f;
    }
    const int maxn=1010;
    int n,m,ans,dx[4]={1,0,-1,0},dy[4]={0,1,0,-1};
    char pic[maxn][maxn];
    bool vis[maxn][maxn],heng[maxn],shu[maxn];
    bool legal(int x,int y){return x>=0 && x<n && y>=0 && y<m;}
    void dfs(int x,int y,int col)
    {
    	vis[x][y]=1;
    	for(int i=0;i<4;i++)
    	{
    		int nx=x+dx[i],ny=y+dy[i];
    		if(legal(nx,ny) && pic[nx][ny]=='#' && !vis[nx][ny])dfs(nx,ny,col);
    	}
    }
    int main()
    {
    	n=read();m=read();
    	for(int i=0;i<n;i++)scanf("%s",pic[i]);
    	bool ass=0;
    	for(int i=0;i<n;i++)for(int j=0;j<m;j++)if(pic[i][j]=='#')ass=1;
    	if(!ass)return puts("0"),0;
    	for(int i=0;i<n;i++)
    	{
    		int ok=0;
    		for(int j=0;j<m;j++)if(pic[i][j]=='#')ok=1;
    		if(!ok)heng[i]=1;
    	}
    	for(int i=0;i<m;i++)
    	{
    		int ok=0;
    		for(int j=0;j<n;j++)if(pic[j][i]=='#')ok=1;
    		if(!ok)shu[i]=1;
    	}
    	for(int i=0;i<n;i++)for(int j=0;j<m;j++)if(heng[i] && shu[j])vis[i][j]=1;//,printf("%d %d
    ",i,j);
    	for(int i=0;i<n;i++)
    	{
    		int ok=0,ok2=0;
    		for(int j=0;j<m;j++)
    		{
    			if(vis[i][j])ok2=1;
    			if(pic[i][j]=='#')
    			{
    				ok++;
    				while(j<m && pic[i][j]=='#')j++;
    			}
    		}
    		if(ok>1 || (!ok2 && !ok))return puts("-1"),0;
    	}
    	for(int i=0;i<m;i++)
    	{
    		int ok=0,ok2=0;
    		for(int j=0;j<n;j++)
    		{
    			if(vis[j][i])ok2=1;
    			if(pic[j][i]=='#')
    			{
    				ok++;
    				while(j<n && pic[j][i]=='#')j++;
    			}
    		}
    		if(ok>1 || (!ok2 && !ok))return puts("-1"),0;
    	}
    	for(int i=0;i<n;i++)for(int j=0;j<m;j++)if(pic[i][j]=='#' && !vis[i][j])dfs(i,j,++ans);
    	printf("%d
    ",ans); 
    	return 0;
    }
    

    E. Quantifier Question

    题解

    没想明白,下次一定。

    F. Résumé Review

    题解

    本人有两种理解。
    第一种理解,我称之为离散拉格朗日数乘法。
    先说目标函数:
    (f(b_1,...,b_n)=sum^{n}_{i=1} b_i*(a_i-b_i^2))
    然后是约束条件::
    (sum b_i=k)
    (0 leq b_i leq a_i)(n) 组。
    讲道理,这种约束条件带有不等式的应该由一种叫KKT条件的东西来解决,
    但是题目中已经说了都是离散的,所以我们先试试求一求目标函数的离散偏导
    $frac{part f}{part b_i} $ = $ b_i(a_i-b_i^2) - (b_i-1)(a_i-(b_i-1)^2) =a_i-3b_i^2+3b_i+1 $ ,显然是一个关于(b_i) 的二次函数,其中(0 leq b_i leq a_i)。很巧的是,这个二次函数的对称轴为(x=frac{1}{2}) ,在(x=1,2,3) 这种离散取值中完全是单调递减的,所以为了让目标函数最大,这些(b_i) 显然应该更靠左更好,只需要满足(sum b_i=k)即可,所以我们就可以完全无视这(n) 个约束条件:(0 leq b_i leq a_i)。剩下的就套用正常拉格朗日数乘的规则,使得目标函数的梯度( abla = (frac{part f}{part b_1} ,...,frac{part f}{part b_n}))与约束条件函数的梯度((1,..,1))平行,当然了这个梯度是离散梯度。
    那么我们二分这个两个梯度向量的比值,分别求出每个(b_i) ,看他们是否和(k) ,直到满足题意为止。
    当然了,二分即便到了最后也有大概率可能会出现(sum b_i>K) 的情况,我们需要对(b_i)进行一些微调,用优先队列维护(min(frac{part f}{part b_i}(ans_i))) ,表示这个(ans)减一后损失的贡献。执行(sum b_i-K) 即可。
    第二种理解,是比较正常的理解。
    也是发现了类似于离散偏导单调递减的性质,那么每次指定一个(i) ,使得(i) 向右移动一格,会使最终答案少一点,我们就让那个减少值每次都最小,这样执行(k) 次一定是最大值。(就相当于在(n) 维空间走(k) 步),后面的操作请参考这里
    复杂度是(O(nlog(max{a_i})^2)),之前我不想要第二个(log),就直接求根公式求得每个(b_i),结果一直错,后来发现是在计算(delta) 的时候爆long long了。。。。其实可以用int_128解决,但是我最后还是认怂写了个二分了。

    #include<bits/stdc++.h>
    using namespace std;
    #define mem(a,b) memset(a,b,sizeof(a))
    typedef long long LL;
    typedef pair<LL,LL> PII;
    #define X first
    #define Y second
    inline LL read()
    {
    	LL x=0,f=1;char c=getchar();
    	while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
    	while(isdigit(c)){x=x*10ll+c-'0';c=getchar();}
    	return x*f;
    }	
    
    const int maxn=100010;
    LL F(LL x,LL y){return x-3ll*y*y+3ll*y-1;}
    LL n,k,a[maxn],L=9e18,R=-9e18,ans[maxn],pos[maxn],minn=9e18;
    priority_queue<PII,vector<PII>,greater<PII> > Q;
    bool judge(LL index)
    {
    	LL sum=0;
    	for(LL i=1;i<=n;i++)
    	{
    		LL left=0,right=a[i]+1;
    		while(right-left>1)
    		{
    			LL mid=left+right>>1ll;
    			if(F(a[i],mid)>=index)left=mid;
    			else right=mid;
    		} 
    		if(F(a[i],left)>=index)pos[i]=left; 
    		else pos[i]=right; 
    		sum+=pos[i];
    	}
    	if(sum-k<minn && sum>=k)
    	{
    		minn=sum-k;
    		for(LL i=1;i<=n;i++)ans[i]=pos[i];
    	}
    	return sum<k;
    }
    int main()
    {
    	n=read();k=read();
    	for(LL i=1;i<=n;i++)a[i]=read(),L=min(L,F(a[i],a[i])),R=max(R,a[i]);
    	while(R-L>1)
    	{
    		LL mid=L+R>>1ll;
    		if(judge(mid))R=mid;
    		else L=mid;
    	}
    	judge(L);judge(R);
    	for(int i=1;i<=n;i++)if(ans[i])Q.push(make_pair(F(a[i],ans[i]),i));
    	while(minn--)
    	{
    		PII now=Q.top();Q.pop();
    		ans[now.Y]--;
    		if(ans[now.Y])Q.push(make_pair(F(a[now.Y],ans[now.Y]),now.Y));
    	}
    	for(int i=1;i<n;i++)printf("%lld ",ans[i]);
    	printf("%lld
    ",ans[n]);
    	return 0;	
    }
    

    废话

  • 相关阅读:
    分享:一个支持并发, 支持异步/同步, 支持http/https, 支持续传的avhttp库
    EvaThumber : 基于URL的图片处理库 (可实现缩略图 | 二维码 | 水印 | 面部识别等)
    Stanford University Introduction to Computational Advertising
    saghul, on code « How do event loops work in Python?
    django orm 自己跟自己一对多关系? django问答求助 python官方论坛 Powered by Discuz!
    台北印象 阮一峰的网络日志
    Connector/ODBC 64 bit windows version
    The Django Book
    使用 libevent 和 libev 提高网络应用性能
    SNA Shared Nothing Architecture
  • 原文地址:https://www.cnblogs.com/FYH-SSGSS/p/12853483.html
Copyright © 2011-2022 走看看