ARC082F - Sandglass(思维)
ARC082 D - Sandglass
Solution
這題睡覺的時候 想了挺久的。
一段時間Δt\Delta tΔt內要么是讓x+Δtx+\Delta tx+Δt對XXX取minminmin,要么是讓x?Δtx-\Delta tx?Δt對000取maxmaxmax。
如果沒有對邊界取max/minmax/minmax/min,就是一個單純的前綴和了。而加上對邊界取max/minmax/minmax/min,對于沒有撞到過邊界的還是一個和之前一樣的前綴和,但如果撞到過邊界答案就會改變。
我們發現有這樣一個性質:
對于[0,X][0,X][0,X]的這一個區間經過若干次操作之后,會存在一個前綴和000貼貼(指之后的值都和000一樣),存在一個后綴和XXX貼貼(指之后的值都和XXX一樣)。
這個性質的來源可以通過下列過程得到:
- 初始有一個區間[L,R]=[0,X][L,R]=[0,X][L,R]=[0,X]表示還沒有和000或XXX貼貼的區間。
- 若這一次是減的,[L′,R′]=[L?Δt,R?Δt][L',R']=[L-\Delta t,R-\Delta t][L′,R′]=[L?Δt,R?Δt],且L′<0L'<0L′<0了,那么當前的[L′,0)[L',0)[L′,0)這一段值就和000貼貼了,也就是說,初始區間中與000貼貼的一部分前綴的長度增加?L′-L'?L′。
- 若這一次是加的,[L′,R′]=[L+Δt,R+Δt][L',R']=[L+\Delta t,R+\Delta t][L′,R′]=[L+Δt,R+Δt],且R′>XR'>XR′>X了,那么當前的(X,R′](X,R'](X,R′]這一段值就和000貼貼了,也就是說,初始區間中與000貼貼的一部分前綴的長度增加R′?XR'-XR′?X。
- 注:這里為了方便不會讓正好等于0,X0,X0,X的數和0,X0,X0,X貼貼。
- (是不是和NOIP2020T4NOIP2020\;T4NOIP2020T4的方法有異曲同工之妙?)
然后我們發現上述過程我們是可以直接模擬的,于是可以求出ai,taia_i,ta_iai?,tai?表示[0,ai)[0,a_i)[0,ai?)最早在taita_itai?時刻與000貼貼,同樣bi,tbib_i,tb_ibi?,tbi?表示與XXX貼貼的我們也能求出來。
然后我們可以預處理000的變化和XXX的變化。
對于(x,y)(x,y)(x,y)這個詢問,如果yyy在xxx時刻之前和000或XXX貼貼了,那就按照0/X0/X0/X之前預處理的答案算即可;如果沒有,那么就表示yyy在xxx時刻之前從來沒有撞到過000或XXX的邊界,因此再求一個前綴和計算就可以了。
時間復雜度O(nlgn)O(nlgn)O(nlgn)。
Code
#include <vector> #include <list> #include <map> #include <set> #include <deque> #include <queue> #include <stack> #include <bitset> #include <algorithm> #include <functional> #include <numeric> #include <utility> #include <sstream> #include <iostream> #include <iomanip> #include <cstdio> #include <cmath> #include <cstdlib> #include <cctype> #include <string> #include <cstring> #include <ctime> #include <cassert> #include <string.h> //#include <unordered_set> //#include <unordered_map> //#include <bits/stdc++.h>#define MP(A,B) make_pair(A,B) #define PB(A) push_back(A) #define SIZE(A) ((int)A.size()) #define LEN(A) ((int)A.length()) #define FOR(i,a,b) for(int i=(a);i<(b);++i) #define fi first #define se secondusing namespace std;template<typename T>inline bool upmin(T &x,T y) { return y<x?x=y,1:0; } template<typename T>inline bool upmax(T &x,T y) { return x<y?x=y,1:0; }typedef long long ll; typedef unsigned long long ull; typedef long double lod; typedef pair<int,int> PR; typedef vector<int> VI;const lod eps=1e-11; const lod pi=acos(-1); const int oo=1<<30; const ll loo=1ll<<62; const int mods=998244353; const int MAXN=600005; const int INF=0x3f3f3f3f;//1061109567 /*--------------------------------------------------------------------*/ inline int read() {int f=1,x=0; char c=getchar();while (c<'0'||c>'9') { if (c=='-') f=-1; c=getchar(); }while (c>='0'&&c<='9') { x=(x<<3)+(x<<1)+(c^48); c=getchar(); }return x*f; } int T[MAXN],numa=0,numb=0,s[MAXN],p0[MAXN],px[MAXN]; PR a[MAXN],b[MAXN]; signed main() {int X=read(),n=read();for (int i=1;i<=n;i++) T[i]=read(); T[n+1]=INF+INF;int L=0,R=X;for (int i=1;i<=n+1;i++){int t=T[i]-T[i-1];if (i&1) {L-=t,R-=t;if (R<0) { numa++,a[numa]=MP(a[numa-1].fi+R-L+1,i); break; }else if (L<0) numa++,a[numa]=MP(a[numa-1].fi-L,i),L=0;}else{L+=t,R+=t;if (L>X) { numb++,b[numb]=MP(b[numb-1].fi+R-L+1,i); break; }else if (R>X) numb++,b[numb]=MP(b[numb-1].fi+R-X,i),R=X; }}p0[0]=0,px[0]=X;for (int i=1;i<=n+1;i++){int t=T[i]-T[i-1];if (i&1) s[i]=s[i-1]-t,p0[i]=max(p0[i-1]-t,0),px[i]=max(px[i-1]-t,0);else s[i]=s[i-1]+t,p0[i]=min(p0[i-1]+t,X),px[i]=min(px[i-1]+t,X);}int Case=read();while (Case--){int x=read(),y=read(),p=lower_bound(T+1,T+n+2,x)-T-1,ans;if (y<a[numa].fi){int t=lower_bound(a+1,a+numa+1,MP(y,-1))-a;if (T[a[t].se]>x) ans=y+s[p]+(x-T[p])*((p&1)?1:-1);else ans=p0[p]+(x-T[p])*((p&1)?1:-1);}else if (X-y<b[numb].fi){int t=lower_bound(b+1,b+numb+1,MP(X-y,-1))-b;if (T[b[t].se]>x) ans=y+s[p]+(x-T[p])*((p&1)?1:-1);else ans=px[p]+(x-T[p])*((p&1)?1:-1);}upmin(ans,X),upmax(ans,0);printf("%d\n",ans);}return 0; }總結
以上是生活随笔為你收集整理的ARC082F - Sandglass(思维)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 创建U盘上的维护系统
- 下一篇: LG P4198 楼房重建(线段树)