Codeforces Round #545 Div. 1自闭记

  A:求出该行该列各有多少个比其小的取max,该行该列各有多少个比其大的取max,加起来即可。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define N 1010
char getc(){char c=getchar();while ((c<‘A‘||c>‘Z‘)&&(c<‘a‘||c>‘z‘)&&(c<‘0‘||c>‘9‘)) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
	int x=0,f=1;char c=getchar();
	while (c<‘0‘||c>‘9‘) {if (c==‘-‘) f=-1;c=getchar();}
	while (c>=‘0‘&&c<=‘9‘) x=(x<<1)+(x<<3)+(c^48),c=getchar();
	return x*f;
}
int n,m,a[N][N],ans[N][N],ans2[N][N],b[N];
signed main()
{
#ifndef ONLINE_JUDGE
	freopen("a.in","r",stdin);
	freopen("a.out","w",stdout);
#endif
	n=read(),m=read();
	for (int i=1;i<=n;i++)
		for (int j=1;j<=m;j++)
		a[i][j]=read();
	for (int i=1;i<=n;i++)
	{
		for (int j=1;j<=m;j++) b[j]=a[i][j];
		sort(b+1,b+m+1);
		int t=unique(b+1,b+m+1)-b-1;
		for (int j=1;j<=m;j++)
		{
			int x=lower_bound(b+1,b+t+1,a[i][j])-b;
			ans[i][j]=max(ans[i][j],x);
			ans2[i][j]=max(ans2[i][j],t-x);
		}
	}
	for (int i=1;i<=m;i++)
	{
		for (int j=1;j<=n;j++) b[j]=a[j][i];
		sort(b+1,b+n+1);
		int t=unique(b+1,b+n+1)-b-1;
		for (int j=1;j<=n;j++)
		{
			int x=lower_bound(b+1,b+t+1,a[j][i])-b;
			ans[j][i]=max(ans[j][i],x);
			ans2[j][i]=max(ans2[j][i],t-x);
		}
	}
	for (int i=1;i<=n;i++)
	{
		for (int j=1;j<=m;j++)
		printf("%d ",ans[i][j]+ans2[i][j]);
		printf("\n");
	}
	return 0;
	//NOTICE LONG LONG!!!!!
}

  B:kmp求出最长border,贪心的每次利用这个border制造新子串即可。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define N 1000010
char getc(){char c=getchar();while ((c<‘A‘||c>‘Z‘)&&(c<‘a‘||c>‘z‘)&&(c<‘0‘||c>‘9‘)) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
	int x=0,f=1;char c=getchar();
	while (c<‘0‘||c>‘9‘) {if (c==‘-‘) f=-1;c=getchar();}
	while (c>=‘0‘&&c<=‘9‘) x=(x<<1)+(x<<3)+(c^48),c=getchar();
	return x*f;
}
int n,m,cnt,nxt[N],cnt2;
char a[N],b[N];
signed main()
{
#ifndef ONLINE_JUDGE
	freopen("a.in","r",stdin);
	freopen("a.out","w",stdout);
#endif
	scanf("%s",a+1);n=strlen(a+1);
	scanf("%s",b+1);m=strlen(b+1);
	for (int i=1;i<=n;i++) if (a[i]==‘1‘) cnt++;
	for (int i=1;i<=m;i++) if (b[i]==‘1‘) cnt2++;
	nxt[0]=-1;
	for (int i=1;i<=m;i++)
	{
		int j=nxt[i-1];
		while (b[j+1]!=b[i]&&j!=-1) j=nxt[j];
		nxt[i]=j+1;
	}
	if (n<m) {printf("%s",a+1);return 0;}
	if (cnt<cnt2||n-cnt<m-cnt2) {printf("%s",a+1);return 0;}
	int X=cnt,Y=n-cnt;
	printf("%s",b+1);X-=cnt2,Y-=m-cnt2;
	cnt=0;for (int i=nxt[m]+1;i<=m;i++) if (b[i]==‘1‘) cnt++;
	cnt2=m-nxt[m]-cnt;
	while (X>=cnt&&Y>=cnt2)
	{
		for (int i=nxt[m]+1;i<=m;i++) putchar(b[i]);
		X-=cnt,Y-=cnt2;
	}
	for (int i=1;i<=X;i++) printf("1");
	for (int i=1;i<=Y;i++) printf("0");
	return 0;
	//NOTICE LONG LONG!!!!!
}

  C:场上写了1h假题意。终于看懂题之后又被之前假题意的做法带偏了。考虑拆点,建出新图后缩点,跑最长链即为答案。因为由图的特殊性容易发现,若新图中有两个点代表原图中同一个点的不同时刻且其弱联通,其一定处于同一SCC中。所以不会出现多次计算同一个点的贡献的情况。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
#define ll long long
#define N 100010
#define M 54
char getc(){char c=getchar();while ((c<‘A‘||c>‘Z‘)&&(c<‘a‘||c>‘z‘)&&(c<‘0‘||c>‘9‘)) c=getchar();return c;}
int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
int read()
{
	int x=0,f=1;char c=getchar();
	while (c<‘0‘||c>‘9‘) {if (c==‘-‘) f=-1;c=getchar();}
	while (c>=‘0‘&&c<=‘9‘) x=(x<<1)+(x<<3)+(c^48),c=getchar();
	return x*f;
}
int n,m,d,p[N],dfn[N*M],low[N*M],stk[N*M],Set[N*M],P[N*M],nxt[N*M],top,cnt,t,ans,a[N][M];
bool flag[N*M];
struct data{int to,nxt;
}edge[N<<1];
void addedge(int x,int y){t++;edge[t].to=y,edge[t].nxt=p[x],p[x]=t;}
int id(int n,int m){return (n-1)*d+m;}
void tarjan(int x,int y)
{
	int k=id(x,y);
	dfn[k]=low[k]=++cnt;
	stk[++top]=k;flag[k]=1;
	for (int i=p[x];i;i=edge[i].nxt)
	if (!dfn[id(edge[i].to,y%d+1)]) tarjan(edge[i].to,y%d+1),low[k]=min(low[k],low[id(edge[i].to,y%d+1)]);
	else if (flag[id(edge[i].to,y%d+1)]) low[k]=min(low[k],dfn[id(edge[i].to,y%d+1)]);
	if (dfn[k]==low[k])
	{
		t++;
		while (stk[top]!=k)
		{
			nxt[stk[top]]=P[t];
			P[t]=stk[top];
			flag[stk[top]]=0;
			Set[stk[top]]=t;
			top--;
		}
		flag[k]=0,Set[k]=t,top--;
		nxt[k]=P[t];P[t]=k;
	}
}
namespace DAG
{
	int p[N*M],n,t,f[N*M],value[N*M];
	struct data{int to,nxt;}edge[N*M];
	void addedge(int x,int y){t++;edge[t].to=y,edge[t].nxt=p[x],p[x]=t;}
	void dp()
	{
		for (int i=1;i<=n;i++)
		{
			for (int j=p[i];j;j=edge[j].nxt)
			f[i]=max(f[i],f[edge[j].to]);
			f[i]+=value[i];
		}
	}
}
signed main()
{
#ifndef ONLINE_JUDGE
	freopen("a.in","r",stdin);
	freopen("a.out","w",stdout);
#endif
	n=read(),m=read(),d=read();
	for (int i=1;i<=m;i++)
	{
		int x=read(),y=read();
		addedge(x,y);
	}
	for (int i=1;i<=n;i++)
		for (int j=1;j<=d;j++)
		{
			char c=getchar();
			while (c!=‘0‘&&c!=‘1‘) c=getchar();
			a[i][j]=c-‘0‘;
		}
	t=0;
	for (int i=1;i<=n;i++)
		for (int j=1;j<=d;j++)
		if (!dfn[id(i,j)]) tarjan(i,j);
	DAG::n=t;
	for (int i=1;i<=n;i++)
		for (int x=1;x<=d;x++)
			for (int j=p[i];j;j=edge[j].nxt)
			if (Set[id(i,x)]!=Set[id(edge[j].to,x%d+1)])
			DAG::addedge(Set[id(i,x)],Set[id(edge[j].to,x%d+1)]);
	memset(flag,0,sizeof(flag));
	for (int i=1;i<=t;i++)
	{
		for (int j=P[i];j;j=nxt[j])
		if (!flag[(j-1)/d+1]&&a[(j-1)/d+1][(j-1)%d+1]) DAG::value[i]++,flag[(j-1)/d+1]=1;
		for (int j=P[i];j;j=nxt[j]) flag[(j-1)/d+1]=0;
	}
	DAG::dp();
	cout<<DAG::f[Set[1]];
	return 0;
	//NOTICE LONG LONG!!!!!
}

  D:看到这张图就容易想到floyd判环。于是先拉两个点出来跑一遍,大约能得到一个2(t+d)=t+d+kc。其中k和c都可以确定。这样大概可以二分一下t,但点数说不定不太够。事实上这个时候直接让所有点一起往前跑第一次撞上就是答案了。因为t+d=kc,当前环上点在d的位置,走t步后刚好走到终点。同时由起点出发的点也刚好走了t步到达终点。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
int read()
{
	int x=0,f=1;char c=getchar();
	while (c<‘0‘||c>‘9‘) {if (c==‘-‘) f=-1;c=getchar();}
	while (c>=‘0‘&&c<=‘9‘) x=(x<<1)+(x<<3)+(c^48),c=getchar();
	return x*f;
}
char s[12];
int main()
{
#ifndef ONLINE_JUDGE
	freopen("b.in","r",stdin);
	freopen("b.out","w",stdout);
#endif
	int cnt=0;
	while (1)
	{
		cout<<"next 1 2"<<endl;
		int x=read();
		for (int i=1;i<=x;i++) scanf("%s",s);
		cout<<"next 1"<<endl;
		x=read();
		for (int i=1;i<=x;i++) scanf("%s",s);
		if (x==2) break;
	}
	while (1)
	{
		cout<<"next 0 1 2 3 4 5 6 7 8 9"<<endl;
		int x=read();
		for (int i=1;i<=x;i++) scanf("%s",s);
		if (x==1) {cout<<"done"<<endl;return 0;}
	}
}

  剩下的先咕着。

  感觉非常可怕的是看完sol不是感叹题好神而是感叹自己傻逼。

  靠着偶尔快起来的切傻逼题的手速上了红,事实上还是打铁实力。简直自闭。

  小号打的。result:rank 254 rating -19

原文地址:https://www.cnblogs.com/Gloid/p/10498984.html

时间: 2024-08-02 09:26:31

Codeforces Round #545 Div. 1自闭记的相关文章

Educational Codeforces Round 58 Div. 2 自闭记

明明多个几秒就能场上AK了.自闭. A:签到. #include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; #define ll long long char getc(){char c=getchar();while ((c<'A'

Codeforces Round #545 (Div. 2) 掉分记

每次CF后,我的rating下降,掉分让我悲痛欲绝 ——题记 ### 前言 这次 CF 时间可谓是极好的,17:05 开始,时长 2h 30min. 4:40 回到家,开电脑. 在看了一会书后,比赛开始了. ### 正文 首先,第一个掉分的 flag 出现了! 卡,卡,卡! CF 又双叒叕卡了! 1分钟过去了…… 2分钟过去了…… 3分钟过去了…… Dashboard 一直打不开.. 当时间已经接近 17:10 分的时候,我终于打开了 A 题.. 然而,这还并不是我掉分的所有原因. 先迅速浏览了

Codeforces Round #545 (Div. 2) D

链接:http://codeforces.com/contest/1138/problem/D 啊啊啊啊啊啊,自闭啊,比赛的时候判断条件 if(s1[i-1]=='0') aa++;写成了 if(s1[i]=='0') aa++;少写了个-1,被hack了,上分场变成了掉分场. 思路; 题目需要t字符串出现次数最多,那么找到最大的重叠部分就好了,然后依次加上就好了 主要就是要找到字符串t与本身的重叠部分,,假设有两个t,第一个t不变,第二个t向右移动: 比如: 10101010 -1010101

Codeforces Round #522 Div. 1 没打记

开场被A劝退,写了得有50min于是不敢交了.unrated了喜闻乐见. A:瞎猜都能猜到如果要走到那条直线上,进入直线的点横坐标或纵坐标与起点相同,离开直线的点横坐标或纵坐标与终点相同,证明脑补一下比较显然.看错题以为到直线上的那个点必须是整点,于是搞了半天exgcd.然而就算这样也不至于写这么长时间啊根本不知道自己在干啥. #include<iostream> #include<cstdio> #include<cmath> #include<cstdlib&

Codeforces Round #545 (Div. 2)A. Sushi for Two

全世界最笨的人 出现了 这题真的好欺骗我的感情,表面上先给我过了,让我快乐一下,背地里再把我给踢掉 TUT干嘛这么坏啊!!!!!!!!!!!!! 好吧,其实这个错误昨天晚上就反过了 但是世界上最笨的女同学她是不会改的 如果你下次还不改 那你还是世界上最笨的女同学 如果你改了 那你...... TUT... 我们来分析一下,为什么这个女同学,连A题都过不了 这题的题意很简单,就是要求长得像AAABBB的序列的最大值 我先选了一种很弱智的方法 就是,先求前面那个连续序列的长度,再求后面那个连续序列的

Codeforces Round #545 (div 1.)

B.Camp Schedule 给两个 $01$ 串 $s$ 和 $t$,你可以将 $s$ 串任意重排,要求最大化 $t$ 在 $s$ 子串中出现的次数,可以重叠 $|s|,|t| \leq 500000$ sol: 看到可以重叠,考虑最大化利用重叠部分 重叠部分是这次 $t$ 串的结束和下次 $t$ 串的开始,也就是 $t$ 串的一个 $border$ 先放一个 $border$ ,之后一直放 $t$ 串的除 $border$ 以外的部分就可以了 #include <bits/stdc++.h

Codeforces Round #545 (Div. 2)D(KMP,最长公共前后缀,贪心)

#include<bits/stdc++.h>using namespace std;const int N=1000007;char s1[N],s2[N];int len1,len2;int nex[N];int cnt1[7],cnt2[7];int main(){    scanf("%s %s",s1+1,s2+1);    len1=strlen(s1+1);    len2=strlen(s2+1);    for(int i=1;i<=len1;i++

Codeforces Round #535 (Div. 3)小上分记

Codeforces Round #535 (Div. 3)小上分记 前言 被拉去买新年衣服了,导致半小时后才进场. 虽然做了4道题,但是rating还是涨得不多. 用predictor看了rating变化后心灰意冷,不看E题了. A ...800的难度. B 本来还在想要不要用什么STL.后来发现直接用桶就行了.然后就可以水过了. C 题意差点理解不了. 就6种情况都去考虑一下,找最小代价的即可.不要考虑少了. 每次都是\(O(n)\)的,所以能搞. D 贪心地换字母即可. E 坑.待填. 原

Codeforces Round #244 (Div. 2)

A. Police Recruits B. Prison Transfer A,B两个是水题. C. Checkposts DFS找出所有的环就行了. 每次搜索一个结点u时,给u加一个递增标号low[u],同时记录搜索u及u的子结点过程中遇到的最小标号minc,也就是当搜索u的子结点v时,minc = min(minc, low[v]).搜索完成后,如果minc < low[u],说明搜索u的子结点时又回到了u的父结点,也就是说u在一个环中,然后求出这个环的最小费用及取到最小费用的结点数. D.