8.5总结

8.5总结

得分

100+85+60

Rank 1~~

终于做了一次人做的比赛

T1

题目大意

给定一个n*m的矩阵,(x,y)的值为(x-1)*m+y。有k次修改操作,每次把一行或一列乘上一个系数y,求矩阵每个数的和

n,m<=1000000;k<=100000

正解

一眼题

首先,修改操作的顺序可以随便调换。

对于每一列,它的和就是(S1*m+S2*i)*yi,这个S1和S2取决于对行的修改,并且对于每一列都不变

第一行对S1的贡献是0*y1,第二行对S1的贡献是1*y2,第三行对S1的贡献是2*y3...以此类推

第一行对S2的贡献是y1,第二行对S2的贡献是y2...以此类推

T2

题目大意


正解

维护一个jump[i]数组表示第1列第i行跳m步会跳会第一列哪一行。

move的时候可以先跳到第一列,再m步m步跳找循环节

难点就在于怎么维护jump[i]数组。

我调了11个小时拿了15分

以下的"-1""+1"可能指循环意义下的增减

更新一个点(x,y)的时候,(x-1,y-1),(x,y-1)与(x+1,y-1)所能到达的第一列的节点可能发生变化,进而影响到第一列某些点的jump[i]。

由于第一列能到达点(x,y)的点一定是一个连续的区间,所以维护区间的端点就可以了。

但是有可能区间是[1~r]与[l~n],所以要特判。

把l--,r++然后往回缩。

如果l--,r++之后代表[1~n]又要特判

#include<cstdio>
#include<cstring>
#include<algorithm>
#define O3 __attribute__((optimize(3)))
using namespace std;

int n,m,Q,i,j,k,tot,ll,rr,lll,rrr,kk,rx,ry,bzz,ggg;
int x,y,z,tox,toy,xx,yy,st,en;
int a[2005][2005];
int bz[2005],l[2005];
char str[15];
int jump[2005];

O3 int read()
{
	int s=0;char ch=getchar();
	while ((ch<'0')||(ch>'9'))
	ch=getchar();
	while ((ch>='0')&&(ch<='9'))
	{
		s=s*10+ch-'0';
		ch=getchar();
	}
	return s;
}

O3 int in(int x,int l,int r)
{
	if (x==-1) return 0;
	if (l<=r)
	{
		if ((x>=l)&&(x<=r)) return 1;
	}
	else
	{
		if ((x<=r)||(x>=l)) return 1;
	}
	return 0;
}

O3 int pre(int x)
{
	return (x+n-2)%n+1;
}

O3 int nex(int x)
{
	return x%n+1;
}

O3 int good(int x,int y)
{
	int tox,toy;
	int xx,yy;
	toy=yy=y%m+1;
	tox=x;
	xx=nex(x);
	if (a[xx][yy]>a[tox][toy])
		tox=xx;
	xx=pre(x);
	if (a[xx][yy]>a[tox][toy])
		tox=xx;
	return tox;
}

O3 void jump_to_end(int k)
{
	int tox,toy;
	while (k--)
	{
		
		toy=y%m+1;
		tox=good(x,y);
		
		x=tox;y=toy;
		if (y==1) break;
	}
}

O3 int getsum(int l,int r)
{
	if (r>=l) return r-l+1;
	else
	{
		return n-l+1+r;
	}
}

O3 void update(int xx,int yy)
{
	int ll,rr,i,lll,rrr;
	rx=x;ry=y;
	x=xx;y=yy;
	jump_to_end(m+1);
	tox=x;
	x=rx;y=ry;
	
	ll=rr=xx;
	bzz=1;
	if (yy==1)
	{
		yy=m+1;
		jump[xx]=tox;
		tox=xx;
	}
	for (i=yy-1;i>=1;i--)
	{
		lll=ll;
		rrr=rr;
		if (getsum(pre(lll),rrr)>=getsum(ll,rr)) lll=pre(lll);
		if (getsum(lll,nex(rrr))>=getsum(ll,rr)) rrr=nex(rrr);
		if (getsum(lll,rrr)==n)
		{
			if (ll<=rr)
			{
				if (ll>1)
				{
					if (ll>2)
					{
						if (!in(good(3,i),ll,rr))
						{
							lll=3;
							rrr=2;
						}
					}
					if (!in(good(2,i),ll,rr))
					{
						lll=2;
						rrr=1;
					}
					if (!in(good(1,i),ll,rr))
					{
						lll=1;
						rrr=n;
					}
					if (!in(good(n,i),ll,rr))
					{
						lll=1;
						rrr=n;
					}
				}
				if (rr<n)
				{
					if (rr<pre(n))
					{
						if (!in(good(pre(pre(n)),i),ll,rr))
						{
							lll=pre(pre(n));
							rrr=pre(pre(pre(n)));
						}
					}
					if (!in(good(pre(n),i),ll,rr))
					{
						lll=pre(n);
						rrr=pre(pre(n));
					}
					if (!in(good(n,i),ll,rr))
					{
						lll=1;
						rrr=n;
					}
					if (!in(good(nex(n),i),ll,rr))
					{
						lll=nex(n);
						rrr=n;
					}
				}
			}
			else
			{
				if (ll==nex(nex(rr)))
				{
					if (!in(good(rr,i),ll,rr))
					{
						lll=rr;
						rrr=pre(rr);
					}
					if (!in(good(nex(rr),i),ll,rr))
					{
						lll=nex(rr);
						rrr=rr;
					}
					if (!in(good(nex(nex(rr)),i),ll,rr))
					{
						lll=nex(nex(rr));
						rrr=nex(rr);
					}
				}
				else
				{
					if (!in(good(rr,i),ll,rr))
					{
						lll=rr;
						rrr=pre(rr);
					}
					if (!in(good(nex(rr),i),ll,rr))
					{
						lll=nex(rr);
						rrr=rr;
					}
					if (!in(good(nex(nex(rr)),i),ll,rr))
					{
						lll=nex(nex(rr));
						rrr=nex(rr);
					}
					if (!in(good(nex(nex(nex(rr))),i),ll,rr))
					{
						lll=nex(nex(nex(rr)));
						rrr=nex(nex(rr));
					}
				}
			}
		}
		while ((!in(good(lll,i),ll,rr)))
		{
			lll=nex(lll);
			if (lll==nex(rrr))
			{
				bzz=0;
				break;
			}
		}
		while ((!in(good(rrr,i),ll,rr)))
		{
			rrr=pre(rrr);
			if (rrr==pre(lll))
			{
				bzz=0;
				break;
			}
		}
		if (bzz==0) break;
		ll=lll;
		rr=rrr;
		if (getsum(ll,rr)==n) break;
	}
	if (bzz==0) return;
	if (ll<=rr)
	{
		for (i=ll;i<=rr;i++)
		if ((yy!=1)||(i!=xx))
		jump[i]=tox;
	}
	else
	{
		for (i=1;i<=rr;i++)
		if ((yy!=1)||(i!=xx))
		jump[i]=tox;
		for (i=ll;i<=n;i++)
		if ((yy!=1)||(i!=xx))
		jump[i]=tox;
	}
}

O3 int main()
{
	freopen("read.in","r",stdin);
	freopen("jump.out","w",stdout);
	scanf("%d%d",&n,&m);
	for (i=1;i<=n;i++)
	{
		for (j=1;j<=m;j++)
		{
			a[i][j]=read();
		}
	}
	for (i=1;i<=n;i++)
	{
		x=i; y=1;
		jump_to_end(m+1);
		jump[i]=x;
	}
	x=1;y=1;
	scanf("%d",&Q);
	while (Q--)
	{
		
		scanf("%s",str+1);
		if (str[1]=='m')
		{
			scanf("%d",&k);
			kk=k-(m-y+1);
			jump_to_end(k);
			k=kk;
			if (k<=0)
			{
				printf("%d %d\n",x,y);
				continue;
			}
			memset(bz,0,sizeof(bz));
			tot=1;
			l[1]=x;
			bz[x]=1;
			while (k>=m)
			{
				if (bz[jump[x]]==0)
				{
					bz[jump[x]]=bz[x]+1;
					l[++tot]=jump[x];
					x=jump[x];
					k-=m;
				}
				else
				{
					en=bz[x];
					st=bz[jump[x]];
					k-=m;
					break;
				}
			}
			
			if (k>=m)
			{
				x=l[st+(k/m)%(en-st+1)];
				k=k%m;
			}
			jump_to_end(k);
			printf("%d %d\n",x,y);
		}
		else
		{
			scanf("%d%d%d",&xx,&yy,&z);
			a[xx][yy]=z;
			update(xx,(yy-2+m)%m+1);
			update(pre(xx),(yy-2+m)%m+1);
			update(nex(xx),(yy-2+m)%m+1);
		}
	}
}

小结

  1. 每道题都一定要做,都要拿分,多看数据的特殊性质。
  2. 时间安排要合理,有计划性
posted @ 2019-08-06 08:51  leason_lyx  阅读(183)  评论(0编辑  收藏  举报