【CF1614E】Divan and a Cottage
阿新 • • 發佈:2021-11-29
題目
題目連結:https://codeforces.com/contest/1614/problem/E
給定 \(n\) 天的氣溫 \(T_i\) ,設第 \(i\) 天溫度為 P ,則第 \(i+1\) 天的溫度為:
- \(P+1\) ( \(P<T_i\) )
- \(P-1\) ( \(P>T_i\) )
- \(P\) ( \(P=T_i\) )
對第 \(i\) 天有 \(k_i\) 個詢問,問若第 \(1\) 天的溫度為 \(x\) ,那麼第 \(i+1\) 天的溫度是多少。
強制線上。
\(n,\sum k\leq 2\times 10^5\),\(0\leq\) 所有氣溫 \(\leq 10^9\)
思路
設 \(f(x)\) 表示如果第一天的氣溫為 \(x\),那麼第 \(i+1\) 天的氣溫會是多少。顯然 \(f(x)\) 是單調不降的。
維護一棵動態開點線段樹,葉子節點 \([x,x]\) 就維護 \(f(x)\),對於每一個區間維護區間內 \(f\) 的最大值(因為單調不降所以其實就是右端點的值)。
然後對於加入新的一天的操作,線上段樹上二分出最後一個氣溫 \(<t\) 的位置 \(p\),以及第一個氣溫 \(>t\) 的位置 \(q\),讓區間 \([0,p]\) 全部 \(+1\),\([q,10^9]\) 全部 \(-1\) 就好。
時間複雜度 \(O((n+\sum k)\log 10^9)\)
程式碼
#include <bits/stdc++.h> using namespace std; const int N=200010,MAXN=N*120; int Q,t,n,last; struct SegTree { int tot,lc[MAXN],rc[MAXN],res[MAXN],lazy[MAXN]; SegTree() { tot=1; res[1]=1e9+1; } void pushdown(int x,int l,int r) { int mid=(l+r)>>1; if (!lc[x]) lc[x]=++tot,res[lc[x]]=mid; if (!rc[x]) rc[x]=++tot,res[rc[x]]=r; if (!lazy[x]) return; res[lc[x]]+=lazy[x]; lazy[lc[x]]+=lazy[x]; res[rc[x]]+=lazy[x]; lazy[rc[x]]+=lazy[x]; lazy[x]=0; } int query(int x,int l,int r,int k) { if (l==r) return res[x]; pushdown(x,l,r); int mid=(l+r)>>1; if (k<=mid) return query(lc[x],l,mid,k); if (k>mid) return query(rc[x],mid+1,r,k); return 114514; } int update(int x,int l,int r,int ql,int qr,int v) { if (ql>qr) return x; if (!x) x=++tot,res[x]=r; if (ql<=l && qr>=r) { res[x]+=v; lazy[x]+=v; return x; } pushdown(x,l,r); int mid=(l+r)>>1; if (ql<=mid) lc[x]=update(lc[x],l,mid,ql,qr,v); if (qr>mid) rc[x]=update(rc[x],mid+1,r,ql,qr,v); res[x]=res[rc[x]]; return x; } int query1(int x,int l,int r,int k) { if (l==r) return (res[x]<=k)?l:l-1; pushdown(x,l,r); int mid=(l+r)>>1; if (res[lc[x]]>k) return query1(lc[x],l,mid,k); if (res[lc[x]]<=k) return query1(rc[x],mid+1,r,k); return 114514; } int query2(int x,int l,int r,int k) { if (l==r) return (res[x]>=k)?l:l+1; pushdown(x,l,r); int mid=(l+r)>>1; if (res[lc[x]]<k) return query2(rc[x],mid+1,r,k); if (res[lc[x]]>=k) return query2(lc[x],l,mid,k); return 114514; } }seg; int main() { scanf("%d",&Q); while (Q--) { scanf("%d%d",&t,&n); int p=seg.query1(1,-1,1e9+1,t-1); int q=seg.query2(1,-1,1e9+1,t+1); seg.update(1,-1,1e9+1,0,p,1); seg.update(1,-1,1e9+1,q,1e9,-1); for (int i=1,x;i<=n;i++) { scanf("%d",&x); x=(x+last)%(int)(1e9+1); last=seg.query(1,-1,1e9+1,x); cerr<<"> "; printf("%d\n",last); } } return 0; }