• 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("
    ");
    	}
    	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;}
    	}
    }
    

      E:显然同时被加入的车只有第一辆可能成为答案,于是可以把同一段的合并起来。先不考虑插入,就是要滋磁整体加一条直线、查最小值。经典做法是对坐标为k初值为b的位置构造一条直线y=kx+b,然后求出所有直线构成的上凸壳,显然最小值只会在凸壳上取得,每次加的时候相当于移动凸壳上当前点的横坐标。

      对于插入,如果是在尾部,相当于插入了一条当前斜率最大的直线,如果其在上凸壳中,一定处于第一个,所以在凸壳头部删直线并插入即可;如果在头部,会对所有直线的斜率产生影响,但可以发现这些直线构成的凸壳不会发生变化。于是相当于插入了一条当前斜率最小的直线,在凸壳尾部删直线并插入即可。修改时加上的常数显然可以改成偏移量处理掉。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define ll long long
    #define N 600010
    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;
    }
    typedef pair<ll,ll> pll;
    int m,head,tail;
    ll n,first,last,deltas,deltab;
    struct line
    {
    	ll k,b;
    	ll f(ll x){return k*x+b;}
    }a[N];
    bool iscover(line x,line y,line z)
    {
    	return (long double)(x.k-y.k)*(z.b-x.b)/(x.k-z.k)<=y.b-x.b;
    }
    void ins_head(ll k,ll b)
    {
    	line l=(line){k,b};
    	while (head<tail&&iscover(l,a[head],a[head+1])) head++;
    	if (head==tail&&l.k<a[head].k&&l.b<=a[head].b) head++;
    	a[--head]=l;
    }
    void ins_tail(ll k,ll b)
    {
    	line l=(line){k,b};
    	while (head<tail&&iscover(a[tail-1],a[tail],l)) tail--;
    	if (head==tail&&l.k<a[head].k&&l.b<=a[head].b) tail--;
    	a[++tail]=l;
    }
    line getans(ll x)
    {
    	int l=head,r=tail;
    	while (l+1<r)
    	{
    		int mid=l+r>>1;
    		if (a[mid-1].f(x)>a[mid].f(x)) l=mid+1;
    		else r=mid-1;
    	}
    	line u=a[tail];
    	for (int i=max(l-2,head);i<=min(l+2,tail);i++)
    	//for (int i=head;i<=tail;i++)
    	if (a[i].f(x)<=u.f(x)) u=a[i];
    	return u;
    }
    signed main()
    {
    #ifndef ONLINE_JUDGE
    	freopen("e.in","r",stdin);
    	freopen("e.out","w",stdout);
    #endif
    	n=read(),m=read();first=1,last=n;
    	head=tail=300005;
    	ll qwq=1;
    	while (m--)
    	{
    		int op=read();
    		if (op==1)
    		{
    			int k=read();n+=k;first-=k;qwq=1;
    			ll b=-deltas*(first-1)-deltab;
    			ins_tail(first-1,b);
    			printf("1 0
    ");
    		}
    		if (op==2)
    		{
    			int k=read();
    			ll b=-deltas*last-deltab;
    			ins_head(last,b);
    			if (!qwq) qwq=n+1;
    			printf("%I64d %d
    ",qwq,0);
    			n+=k;last+=k;
    		}
    		if (op==3)
    		{
    			int b=read(),s=read();qwq=0;
    			deltab+=b+1ll*(1-first)*s,deltas+=s;
    			line ans=getans(deltas);
    			printf("%I64d %I64d
    ",ans.k+2-first,ans.f(deltas)+deltab);
    		}
    		//for (int i=head;i<=tail;i++) cout<<a[i].k<<' '<<a[i].b<<endl;cout<<endl;
    	}
    	return 0;
    	//NOTICE LONG LONG!!!!!
    }

      F先咕着。

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

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

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

  • 相关阅读:
    MARKY一下。
    从一个git仓库拷贝到另一个git仓库
    Git:四、连接GitHub远程仓库
    木门工厂木门、门套、套线公式和算法
    设计模式之代理模式
    2018年软件开发状态报告
    产品研发流程与周期(非原创)
    软件工程师的核心竞争力
    linux下安装redis安装使用
    8 个 Tips 让你更好的进行 Code Review
  • 原文地址:https://www.cnblogs.com/Gloid/p/10498984.html
Copyright © 2020-2023  润新知