NOIP 模擬 $20\; \rm z$
阿新 • • 發佈:2021-07-22
題解
不能寫成
題解
很考驗思維的一道題
對於不同的任務點,發現如果 \(x_{i-1}<x_i<x_{i+1}\) 或 \(x_{i-1}>x_i>x_{i+1}\) 那麼 \(x_i\) 這個位置的數就沒用了
將序列先掃一遍,合併不同的位置,然後將合併後的 \(x_i->x_{i+1}\) 按距離排序,再將詢問序列從小到大排序,離線詢問
用一個 \(map\) 儲存所有 \(x_{i}->x_{i+1}\) 的任務編號,二分查詢當前點
那麼當一個長度大於這段區間了,它就會超出範圍,要將它左右的區間和它合併
注意:ans[c[t].id]=calc(ans[c[t].l),t++
ans[c[t].id]=calc(ans[c[t++].l)
,因為在高版本 c++ 中是從右往左編譯的
Code
#include<bits/stdc++.h> #define ri register signed #define p(i) ++i using namespace std; namespace IO{ char buf[1<<21],*p1=buf,*p2=buf; #define gc() p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++ template<typename T>inline void read(T &x) { ri f=1;x=0;register char ch=gc(); while(ch<'0'||ch>'9') {if (ch=='-') f=0;ch=gc();} while(ch>='0'&&ch<='9') {x=(x<<1)+(x<<3)+(ch^48);ch=gc();} x=f?x:-x; } } using IO::read; namespace nanfeng{ #define node(id,x) (node){id,x} #define FI FILE *IN #define FO FILE *OUT template<typename T>inline T cmax(T x,T y) {return x>y?x:y;} template<typename T>inline T cmin(T x,T y) {return x>y?y:x;} typedef long long ll; static const int N=1e5+7; struct node{int id;ll x;}al[N]; inline int operator<(const node &n1,const node &n2) {return n1.x>n2.x;} inline int cmp(node n1,node n2) {return n1.x<n2.x;} priority_queue<node> que; map<int,int> mp; int n,q,cnt,t=1; ll sum,dx[N],ans[N]; inline ll calc(ll l) { if (mp.empty()) return 0; if (mp.begin()->second<0) return sum-(mp.size()-1)*l; return sum-mp.size()*l; } inline int main() { // FI=freopen("nanfeng.in","r",stdin); // FO=freopen("nanfeng.out","w",stdout); read(n),read(q); ri lst=0; for (ri i(1),x;i<=n;p(i)) { read(x); if (x==lst) continue; if (cnt&&(dx[cnt]<0&&x-lst<0||dx[cnt]>0&&x-lst>0)) dx[cnt]+=x-lst; else dx[p(cnt)]=x-lst; lst=x; } for (ri i(1),l;i<=q;p(i)) read(l),al[i].x=l,al[i].id=i; sort(al+1,al+q+1,cmp); for (ri i(1);i<=cnt;p(i)) { sum+=abs(dx[i]); mp[i]=dx[i]; que.push(node(i,abs(dx[i]))); } while(!que.empty()) { node tmp=que.top();que.pop(); auto it=mp.lower_bound(tmp.id); if (it==mp.end()) continue; node nw=node(it->first,it->second); if (abs(nw.x)!=tmp.x||nw.id!=tmp.id) continue; while(t<=q&&tmp.x>al[t].x) ans[al[t].id]=calc(al[t++].x); auto bg=mp.begin(); if (it!=mp.begin()) { if (it!=prev(mp.end())) { auto pr=prev(it),nx=next(it); node tmpr=node(pr->first,pr->second); node tmpn=node(nx->first,nx->second); mp.erase(pr);mp.erase(nx); sum-=abs(nw.x); sum-=abs(tmpr.x); sum-=abs(tmpn.x); tmp.x=nw.x; tmp.x+=tmpr.x; tmp.x+=tmpn.x; it->second=tmp.x; tmp.x=abs(tmp.x); sum+=tmp.x; que.push(tmp); } else { sum-=abs(nw.x); mp.erase(it); } } else { if (nw.x>0) { if (it!=prev(mp.end())) { auto nx=next(it); node tmpn=node(nx->first,nx->second); mp.erase(nx); sum-=abs(nw.x); sum-=abs(tmpn.x); tmp.x=nw.x; tmp.x+=tmpn.x; if (tmp.x) { it->second=tmp.x; tmp.x=abs(tmp.x); sum+=tmp.x; que.push(tmp); } else mp.erase(it); } else { sum-=abs(tmp.x); mp.erase(it); } } } } while(t<=q) ans[al[t].id]=calc(al[t++].x); for (ri i(1);i<=q;p(i)) printf("%lld\n",ans[i]); return 0; } } int main() {return nanfeng::main();}