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