ICode9

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

2019ICPC南昌网络赛 - I. Yukino With Subinterval

2019-09-09 18:35:53  阅读:426  来源: 互联网

标签:p1 Subinterval int Yukino 2019ICPC maxn && nlogn define


题意:

给定一个长为 n 的数组,定义值相同的区间为一子段,有 m 个操作,①:1,pos,v,修改 pos 上的值为 v;②:2,l,r,x,y,询问区间 [ l, r ] 的值域在 [ x, y ] 的段个数,只计最长段。(n, m <= 2e5)

链接:

https://nanti.jisuanke.com/t/41356

题解:

考虑将段转化为点,令 b[i] = a[i] != a[i - 1] ? a[i] : 0,则查询操作转化为求区间 [ l + 1, r ] 的值在 [ x, y ] 的元素个数(l 位置上必然满足为段,单独检查值域即可),修改则维护 b[ pos - 1 ],b[ pos ] 和 b[ pos + 1 ] 即可。显然树状数组套主席树可解(常数巨大),但我又不会 cdq 分治。 那么就愉快分块吧!考虑分块,为了愉快卡常过题,块内套树状数组,则修改操作为 O(logn)。查询涉及整块的块内 logn 查询以及角块暴力,令块大小为 nlogn\sqrt{nlogn}nlogn​,则整块数目为 nnlogn\cfrac{n}{\sqrt{nlogn}}nlogn​n​,整块查询复杂度 O(nlogn\sqrt{nlogn}nlogn​),角块也是 O(nlogn\sqrt{nlogn}nlogn​),单次查询复杂度为 O(nlogn\sqrt{nlogn}nlogn​)。然后就卡过去了。

参考代码:

#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
#define pb push_back
#define sz(a) ((int)a.size())
#define mem(a, b) memset(a, b, sizeof a)
#define lson (rt << 1)
#define rson (rt << 1 | 1)
#define gmid (l + r >> 1)
const int maxn = 2e5 + 5;
const int maxm = 5e2 + 5;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;

int a[maxn], b[maxn];
int li[maxm], ri[maxm], id[maxn];
int c[maxm][maxn];
int n, m;

const int maxs = 1e3 + 5;
char buf[maxs], *p1 = buf, *p2 = buf;
inline char fr(){

	return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, maxs, stdin)) == p1 ? -1 : *p1++;
}
#define gc fr()
inline void read(int &x){

	char ch; while(!isdigit(ch = gc)); x = ch ^ 48;
	while(isdigit(ch = gc)) x = x * 10 + (ch ^ 48);
}

#define lowb(x) ((x)&(-x))
void update(int x, int v, int c[]){

	while(x < maxn) c[x] += v, x += lowb(x);
}

int query(int x, int c[]){

	int ret = 0;
	while(x) ret += c[x], x -= lowb(x);
	return ret;
}

void build(){

	int len = sqrt(log(n + 1) * n);
	for(int i = 1; i <= n; ++i) id[i] = (i - 1) / len + 1;
	for(int i = 1; i <= id[n]; ++i) li[i] = (i - 1) * len + 1, ri[i] = i * len; ri[id[n]] = n;
	for(int i = 1; i <= n; ++i) if(b[i]) update(b[i], 1, c[id[i]]);
}

void Update(int x, int v){

	if(v == a[x]) return;
	if(x < n && v == a[x + 1]) update(b[x + 1], -1, c[id[x + 1]]), b[x + 1] = 0;
	if(x > 1 && v == a[x - 1] && b[x]) update(b[x], -1, c[id[x]]), b[x] = 0;
	else{

		if(b[x]) update(b[x], -1, c[id[x]]);
		b[x] = v, update(b[x], 1, c[id[x]]);
	}
	a[x] = v;
}

int Query(int l, int r, int x, int y){

	if(l > r) return 0;
	int p1 = id[l], p2 = id[r], ret = 0;
	if(p1 == p2){

		for(int i = l; i <= r; ++i) ret += b[i] >= x && b[i] <= y;
		return ret;
	}
	for(int i = p1 + 1; i < p2; ++i) ret += query(y, c[i]) - query(x - 1, c[i]);
	for(int i = l; i <= ri[p1]; ++i) ret += b[i] >= x && b[i] <= y;
	for(int i = li[p2]; i <= r; ++i) ret += b[i] >= x && b[i] <= y;
	return ret;
}

int main(){

	read(n), read(m);
	for(int i = 1; i <= n; ++i) read(a[i]), b[i] = a[i] != a[i - 1] ? a[i] : 0;
	build();
	while(m--){

		int opt, l, r, x, y; read(opt), read(l), read(r);
		if(opt == 1) Update(l, r);
		else{

			read(x), read(y);
			int ret = Query(l + 1, r, x, y) + (a[l] >= x && a[l] <= y);
			printf("%d\n", ret);
		}
	}
}

 
cdq 分治待补。

标签:p1,Subinterval,int,Yukino,2019ICPC,maxn,&&,nlogn,define
来源: https://blog.csdn.net/weixin_44059127/article/details/100670071

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

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

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

ICode9版权所有