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);
}
}
}
小结
- 每道题都一定要做,都要拿分,多看数据的特殊性质。
- 时间安排要合理,有计划性