ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[2018 集训队互测 Day 1] 完美的队列

2022-07-11 20:32:25  阅读:175  来源: 互联网

标签:pre int ed 询问 ++ 2018 include Day 互测


一、题目

点此看题

二、解法

突破本题的关键是全局询问,对于每个询问 \((l,r,x)\),考虑计算出它完全消失的时间 \(ed_i\),那么在 \([i,ed_i)\) 这段时间内权值 \(x\) 都是出现的。所以如果我们处理出了所有 \(ed_i\),可以直接回答询问。

处理 \(ed_i\) 并不好直接 polylog,考虑将原序列分块。那么每个询问会被拆分成若干个整块和散块,我们分别处理整块和散块对询问的贡献即可。(贡献的含义是,把被弹出的时间拿给询问取最大值)

考虑整块对询问的贡献,直接对所有询问 two-pointers,我们维护当前局面最大的 \(a_i\) 记为 \(mx\),再维护一个整体覆盖次数记为 \(tag\),那么如果 \(mx>tag\) 就右移右端点。

加入一个询问时,如果它覆盖了整个块,那么直接修改 \(tag\),否则暴力修改这个块的一部分,暴力重新计算 \(mx\),移动左端点时删除询问。由于所有快重构的总次数不超过 \(O(m)\),均摊下来复杂度 \(O(m\sqrt n)\)

考虑散块对询问的贡献,我们把在这个块内拥有散块的询问取出来,称这种询问为 \(z\) 询问。先枚举块内的单点,然后直接对 \(z\) 询问 two-pointers(必须要把这个单点弹出),需要预处理这些东西:

  • 前 \(i\) 个询问覆盖整个块的总次数 \(pre_i\)
  • 第 \(i\) 个 \(z\) 询问的上一个覆盖整个块的询问编号 \(lst_i\)

因为右端点不一定是 \(z\) 询问,可能是一个覆盖整个块的询问,这可以通过分类讨论解决。

时间复杂度 \(O(m\sqrt n)\)

#include <cstdio>
#include <vector>
#include <iostream>
#include <cmath>
using namespace std;
const int M = 100005;
int read()
{
	int x=0,f=1;char c;
	while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;}
	while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
	return x*f;
}
int n,m,k,ans,a[M],b[M],l[M],r[M],x[M],ed[M];
int mx,tg,L,R,c[M],d[M],pre[M],lst[M],cnt[M];
vector<int> v[M];
void get()
{
	mx=-1e9;
	for(int i=L;i<=R;i++) mx=max(mx,b[i]);
}
void add(int l,int r,int c)
{
	if(l<=L && R<=r) {tg+=c;return ;}
	if(L>r || l>R) return ;
	for(int i=max(l,L);i<=min(r,R);i++)
		b[i]+=c;
	get();
}
void work()
{
	int t=0,o=0;get();tg=0;
	for(int i=1,j=2;i<=m;i++)
	{
		while(j<=m && mx+tg>0)
			add(l[j],r[j],-1),j++;
		pre[i]=pre[i-1];
		if(l[i]<=L && R<=r[i])
		{
			ed[i]=max(ed[i],mx+tg>0?m+1:j-1);
			c[++t]=i;pre[i]++;
		}
		else if(L<=r[i] && l[i]<=R)
			d[++o]=i,lst[o]=t;
		add(l[i+1],r[i+1],1);
	}
	for(int i=L;i<=R;i++)
	{
		tg=a[i];
		for(int j=1,k=1;j<=o;j++)
		{
			while(k<o && tg>0)
				k++,tg-=pre[d[k]]-pre[d[k-1]]+
				(l[d[k]]<=i && i<=r[d[k]]);
			if(l[d[j]]<=i && i<=r[d[j]])
			{
				if(tg<=0)
				{
					int f=l[d[k]]<=i && i<=r[d[k]];
					if(f && tg==0)
						ed[d[j]]=max(ed[d[j]],d[k]);
					else
						ed[d[j]]=max(ed[d[j]],c[lst[k]+tg+f]);
				}
				else
				{
					if(tg<=pre[m]-pre[d[o]])
						ed[d[j]]=max(ed[d[j]],c[lst[o]+tg]);
					else
						ed[d[j]]=m+1;
				}
			}
			tg+=pre[d[j+1]]-pre[d[j]]+
			(l[d[j+1]]<=i && i<=r[d[j+1]]);
		}
	}
}
signed main()
{
	n=read();m=read();k=sqrt(n);
	for(int i=1;i<=n;i++) a[i]=b[i]=read();
	for(int i=1;i<=m;i++)
		l[i]=read(),r[i]=read(),x[i]=read();
	for(int T=0;T*k<n;T++)
		L=T*k+1,R=min(n,L+k-1),work();
	for(int i=1;i<=m;i++)
	{
		if(!(cnt[x[i]]++)) ans++;
		v[ed[i]].push_back(x[i]);
		for(int x:v[i])
			if(!(--cnt[x])) ans--;
		printf("%d\n",ans);
	}
}

标签:pre,int,ed,询问,++,2018,include,Day,互测
来源: https://www.cnblogs.com/C202044zxy/p/16467765.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有