【CF1614E】Divan and a Cottage
题目
题目链接: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;
}