T1 浮游大陆的68号岛
T2 Chtholly Nota Seniorious
T1
这个题还是比较简单的,毕竟是第一题。
首先,不要想复杂的数据结构,因为中间没有修改值,蒟蒻就是因为高大上的数据结构不精通,所以没有走弯路喽。
用一个前缀和来记录储物点的物件数目;
dis数组记录到1点的距离;
cost数组记录前i个储物点的物品都搬到1点的花费。
接下来就是模拟了。
分为三种情况
x<=l,ans=(cost[r]-cost[l-1])-dis[x]*(sum[r]-sum[l-1]);用都搬到1点的花费减去每个物品从x点到1点的花费,就是答案了。
x>=r;
l< x< r;
后面这两种与前面类似。
注意取摸,如果变为负数,就+mod再%mod(这一点蒟蒻细心地想到了QAQ)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#define LL long long
using namespace std;
const int MOD=19260817;
const int N=200009;
LL a[N],sum[N],dis[N],cost[N],ans;
int n,m;
int main()
{
scanf("%d%d",&n,&m);
for(int i=2;i<=n;i++) scanf("%lld",&dis[i]),(dis[i]+=dis[i-1])%=MOD;
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
sum[i]=(sum[i-1]+a[i])%MOD;
cost[i]=(cost[i-1]+a[i]*dis[i]%MOD)%MOD;
}
for(int i=1;i<=m;i++)
{
ans=0;
int x,l,r;
scanf("%d%d%d",&x,&l,&r);
if(x<=l)
{
ans=((cost[r]-cost[l-1]+MOD)%MOD-(dis[x]*(sum[r]-sum[l-1]+MOD))%MOD+MOD)%MOD;
}
else
if(x>=r)
{
ans=(dis[x]*(sum[r]-sum[l-1]+MOD)%MOD-(cost[r]-cost[l-1]+MOD)%MOD+MOD)%MOD;
}
else
if(x<r&&x>l)
{
ans=(dis[x]*(sum[x]-sum[l-1]+MOD)%MOD-(cost[x]-cost[l-1]+MOD)%MOD+MOD)%MOD;
ans+=((cost[r]-cost[x]+MOD)%MOD-dis[x]*(sum[r]-sum[x]+MOD)%MOD+MOD)%MOD;
ans=ans%MOD;
}
printf("%lld\n",ans);
}
return 0;
}
T2
二分+贪心+矩阵旋转
先把矩阵存四遍,旋转的四个。
显然,肯定把最大值和最小值放到不同的两部分。
那么把四个矩阵,从左上角一行一行地拓展第一部分,右下角一行一行地拓展第二部分。
左上角的条件我们设为a[i][j]< minn+x,右下角的条件设为a[i][j]>maxn-x.
拓展时,采用贪心的策略,左上角的只要满足条件且比上一行的短或相同,就一直拓展(不超过上一行是因为要满足只拐一次弯)。
右下角亦然。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#define LL long long
using namespace std;
const int N=2009;
const int inf=2e9+100;
int n,m,maxn,minn=inf;
int a[4][N][N],en[N];
void init()
{
int x;
scanf("%d%d",&n,&m);
int x1=m,y1=1,x2=n,y2=m,x3=1,y3=n;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
scanf("%d",&x);
a[0][i][j]=x;
a[1][x1--][y1]=x;
a[2][x2][y2--]=x;
a[3][x3++][y3]=x;
minn=min(minn,x);
maxn=max(maxn,x);
}
y1++;x1=m;
x2--;y2=m;
y3--;x3=1;//旋转存4个矩阵
}
}
bool check_map(int k,int x)
{
memset(en,0,sizeof(en));
int nn=n,mm=m;
if(k&1) swap(nn,mm);
en[0]=mm+1;
int i,j;
for(i=1;i<=nn;i++)
{
for(j=1;j<en[i-1];j++)//小于等于上一行
{
if(a[k][i][j]<=minn+x) continue;
else break;
}
en[i]=j;
}
for(i=nn;i>=1;i--)
{
for(j=mm;j>=en[i];j--)
{
if(a[k][i][j]>=maxn-x) continue;
else return 0;
}
}
return 1;
}
bool check(int x)
{
if(check_map(0,x)) return 1;
if(check_map(1,x)) return 1;
if(check_map(2,x)) return 1;
if(check_map(3,x)) return 1;
return 0;
}
int main()
{
//freopen("sample.in","r",stdin);
init();
int L=0,R=maxn-minn,mid;
while(L<=R)
{
mid=(L+R)>>1;
if(check(mid)) R=mid-1;
else L=mid+1;
}
printf("%d",L);
return 0;
}