【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;
}
posted @ 2021-11-29 13:02  stoorz  阅读(73)  评论(0编辑  收藏  举报