洛谷10月月赛R2·浴谷八连测R3 -Chtholly-

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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章