1. 程式人生 > 其它 >【CF1614E】Divan and a Cottage

【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;
}