ICode9

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

[Ynoi2015] 我回来了

2022-08-21 02:00:52  阅读:133  来源: 互联网

标签:ch end log int Ynoi2015 ln include 回来


题传

7 个月后再来看这道题,还是感觉太妙了。

由于答案最终输出 \(E \times Len\),所以本质上是问 \(\forall d \in[L, R]\) 的贡献和,再进一步想,亵渎的要求就是寻找序列

\[x_i=\varepsilon(\exists h_i| h_i\in [(i-1)d+1, id]) \]

从 \(i=1\) 开始的最长连续的 1 段,最长段不好求,转化为求结束的位置,设 \(pos_x\) 为高度 \(x\) 最早出现的位置(不存在则为 \(0\)),则结束的位置 \(end\) 应该满足:

\[\varepsilon(\nexists h_i| h_i\in [(end-1)d+1, end\times d])=\sum_{i=(end-1)d+1}^{end\times d} pos_i=0 \]

现在要搞定的就是这个东西了。

考虑没有增加随从操作怎么做,由于每一个不同的 \(d\) 最多形成的块有 \(n+n/2+n/3+\dots+n/n=n\ln(n)\) 个,我们直接暴力把这 \(n\ln(n)\) 个块的答案整出来(其实也就是对于每个 \(d\),把对应的 \(x_i\) 搞出)。

考虑记 \(time_{d, i}\) 为块长为 \(d\) 时,第 \(i\) 个块最早什么时候有 1,不难写出:

\[time_{d_,i}=\min_{(i-1)d+1\le j\le id} pos_j \]

这个显然就可以 ST 表做出来了把,复杂度 \(O(n \log n+n\ln(n))\) 分别是 ST 表预处理的 \(O(n \log n)\),询问个数 \(n\ln(n)\) 乘上 ST 表询问复杂度 \(O(1)\) 的 \(O(n\ln(n))\)。

显然第 \(i\) 块产生贡献需要满足前 \(i-1\) 块都有值,所以我们还需要对每一个 \(time_{d, i}\) 取前缀 \(\max\)。

现在我们得到了这个 \(time_{d, i}\),也就相当于知道了这一块的贡献将在什么时候产生,直接丢到这个时刻上面就行了,单点修改、区间查询,显然树状数组更好。

复杂度 \(O(n\ln(n)\log n)=O(n\log^2n)\)。

Code:

#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <vector>
#include <cctype> 
using namespace std;
inline int read(){
	char ch=getchar();int x=0, f=1;
	while(!isdigit(ch)) f=(ch=='-'?-1:f), ch=getchar();
	while(isdigit(ch)) x=(x<<3)+(x<<1)+ch-'0', ch=getchar();
	return x*f;
}
const int N=1e5+5;
const int M=1e6+5;
int n, m, lg[N], f[N][20], pos[N];
vector <int> V[M];
pair <int, int> box[M];
int query(int l, int r){//查询最小值 
	int k=lg[r-l+1];
	return min(f[l][k], f[r-(1<<k)+1][k]);
}
int BIT[N];
#define lowbit(x) (x&(-x))
void add(int x){for(; x<=n; x+=lowbit(x)) BIT[x]++;}
int query(int x){
	int ret=0;
	for(; x; x-=lowbit(x)) ret+=BIT[x];
	return ret;
}
#undef lowbit
inline int min(int a, int b){return a=(a<b?a:b);}
int main(){
	n=read(), m=read();
	for(int i=1; i<=n; i++) pos[i]=m+1;
	for(int i=1, opt, x; i<=m; i++){
		opt=read();
		if(opt&1) x=read(), pos[x]=min(pos[x], i), box[i].first=false;
		else box[i].first=read(), box[i].second=read();
	}
	for(int i=2; i<=n; i++) lg[i]=lg[i>>1]+1;
	for(int i=1; i<=n; i++) f[i][0]=pos[i];
	for(int j=1; j<=18; j++)
		for(int i=1; i+(1<<j)-1<=n; i++)
			f[i][j]=min(f[i][j-1], f[i+(1<<j-1)][j-1]);
	for(int d=1; d<=n; d++){
		int Mx=0, tim;add(d);
		for(int l=1, r; l<=n; l=r+1){
			r=min(n, l+d-1);
			tim=query(l, r);Mx=max(Mx, tim);//求出 time(d,j) 并取前缀 max
			V[Mx].push_back(d); 
		}
	}
	for(int i=1; i<=m; i++){
		for(auto j : V[i]) add(j);
		if(box[i].first) printf("%d\n", query(box[i].second)-query(box[i].first-1));
	}
	return 0;
}

标签:ch,end,log,int,Ynoi2015,ln,include,回来
来源: https://www.cnblogs.com/sizeof127/p/16609234.html

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

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

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

ICode9版权所有