1. 程式人生 > >[NOIP10.4模擬賽]3.z題解--思維

[NOIP10.4模擬賽]3.z題解--思維

處理 sum include 數據 esp first prior Y軸 遇到

題目鏈接:

咕咕

閑扯:

哈哈這道T3考場上又敲了5個namespace,300+行,有了前車之鑒還對拍過,本以為子任務分穩了

結果只有30分哈哈,明明用極限數據對拍過不知怎麽回事最後數據又是讀不全,玄學,要是NOIP這樣就GG了

首先第一個子任務貪心模擬即可,但是第二個子任務就像NOID1T1,你啥也不能輸出但是我輸出了0哈哈,真的是傻到家了,第三個子任務簡單考慮一下即可;第四個子任務已經想到了偏正解的做法,但是用了個很SB的方法維護,昨天的T3也是這樣但是都GG了...感覺退役欽定了

感謝WYT大佬正解講解,高一神仙tql

分析:

先考慮第四個子任務,我說一下我在考場上的做法,我們設\(pos[i]\)

是第i個任務的坐標,同時先將區間長度排序離線處理

先考慮pos[1]>0的情況,我們把相鄰正負兩點看成一對處理,所以我們可以一開始在負的點值那裏加一個0點這樣就湊成對了,考慮從一個負點右移到一個正點的時候,如果都不會出現不用右移的情況(也就是不會有直接覆蓋正點的情況)答案就是上一次的總長度減去點個數乘以區間長度之差

但是如果出現了這種情況呢?首先我們離線處理是已經將區間長度從小到大排序,所以當前區間長度是這種情況下一個區間的長度肯定還會是這種情況。

所以遇到這種情況我們需要減去計算之前區間長度在這兩點之間需要的移動距離,再將這兩個踢出我們的考慮範圍(我比較傻用了兩個堆存儲一個正點一個負點,由於是正值或負值是分別單調的只需要兩個指針即可完成操作),同時點數減去2(成對考慮),再次計算貢獻即可

pos[1]<0再分類討論一下就好了

這種情況經過了對拍的檢驗應該是沒什麽問題的但是數據沒讀全也不知道咋回事

然後正解是怎麽處理這個子任務的呢?我們可以把任務編號看成x軸,坐標位置看成y軸點出所有的點再將相鄰兩點連線是這個樣子:

技術分享圖片

我們將相鄰兩點之間連線的長度叫做\(p[i]\),當前區間長度為\(L\),如果任意\(p[i]>L\)那麽答案就是\(\sum (p[i]-L)\)

但是如果存在\(p[i]<=L\)呢,若\(a,b\)連線長度\(p<=L\),那麽我們將這兩點刪去,將\(a-1,b+1\)之間連新的線

技術分享圖片

你會發現由於連線長度是單調的非常好處理,實際上我的做法也是在模擬類似的操作

再考慮沒有第四個子任務的限制怎麽做.首先我們可以預處理,對於一段連續的任務如果是單調的,那麽我們只用保留頭和尾就可以了,中間的顯然不用管,那麽這時候再仿照上面畫出圖像

技術分享圖片

會發現由於並沒有任務4的限制預處理後還可能出現x這樣的點,這時候連線長度就不是遞增的了,怎麽辦呢?

我們把所有長度放入一個小根堆中,每次對於一個新區間長度L,如果堆頂長度p小於等於L,也就是說達到x-1時就已經覆蓋了x,比如圖中\(x-1\)\(x\)這段折線,我們就把它相鄰兩段連線包括它本身換成另一條折線,這樣顯然是最優情況

所以我們還需要記錄連線的前驅後繼來個映射,還要用鏈表/map記錄下對應位移序列之類的搞一搞,統計方案用上面一樣的方法,不斷更新連線段數和連線總長就好了

由於每段只會進堆一次,時間復雜度\(O(NlogN)\)

但是這道題細節巨坑...題解只說了在首尾要特判,但其實鏈表之類搞一搞真挺煩的,所以並沒有寫代碼...

代碼:

這是標程代碼...我太懶了並沒有自己寫一份

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
const int maxn=1e5+10;
int n,m;
ll tot,ans[maxn];
vector<int> x;
vector<pair<int,int> > a;
map<int,int> mp;

inline ll calc(ll k){
    if(!mp.empty()&&mp.begin()->second<0)
        return tot-(mp.size()-1)*k;
    else
        return tot-mp.size()*k;
}
inline void solve(){
    priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > > q;
    int t=0;
    for(int i=0;i<x.size();++i){
        tot+=abs(x[i]);
        mp[i]=x[i];
        q.push(make_pair(abs(x[i]),i));
    }
    while(!q.empty()){
        int id=q.top().second,tmp=q.top().first;q.pop();
        map<int,int>::iterator p=mp.lower_bound(id);
        if(p==mp.end()||p->first!=id||abs(p->second)!=tmp)
            continue;
        while(t<a.size()&&abs(p->second)>a[t].first)
            ans[a[t].second]=calc(a[t].first),++t;
        if(p!=mp.begin())
            if(p!=prev(mp.end())){
                tmp=p->second,tot-=abs(p->second);
                tmp+=prev(p)->second,tot-=abs(prev(p)->second);
                tmp+=next(p)->second,tot-=abs(next(p)->second);
                mp.erase(prev(p));
                mp.erase(next(p));
                p->second=tmp,tot+=abs(tmp);
                q.push(make_pair(abs(tmp),id));
            }
            else{
                tot-=abs(p->second);
                mp.erase(p);
            }
        else if(p->second>0)
            if(p!=prev(mp.end())){
                tmp=p->second,tot-=abs(p->second);
                tmp+=next(p)->second,tot-=abs(next(p)->second);
                mp.erase(next(p));
                if(tmp){
                    p->second=tmp,tot+=abs(tmp);
                    q.push(make_pair(abs(tmp),id));
                }
                else
                    mp.erase(p);
            }
            else{
                tot-=abs(p->second);
                mp.erase(p);
            }
    }
    while(t<a.size())
        ans[a[t].second]=calc(a[t].first),++t;
}

int main(){
    freopen("z.in","r",stdin);
    freopen("z.out","w",stdout);
    scanf("%d%d",&n,&m);
    for(int i=0,p,last=0;i<n;++i){
        scanf("%d",&p);
        if(p==last)
            continue;
        if(!x.empty()&&(x.back()<0&&p<last||x.back()>0&&p>last))
            x.back()+=p-last;
        else
            x.push_back(p-last);
        last=p;
    }
    for(int i=0,l;i<m;++i){
        scanf("%d",&l);
        a.push_back(make_pair(l,i));
    }
    sort(a.begin(),a.end());
    solve();
    for(int i=0;i<m;++i)
        printf("%lld\n",ans[i]);
    return 0;
}

[NOIP10.4模擬賽]3.z題解--思維