Codeforces 813E 主席树

题意:给你一个数组a,有m次询问,每次问区间[l, r]中最多可以取多少个数字(相同的数字最多取k个),强制在线。

思路:可以先预处理一个数组b,b[i]指和a[i]相同的从i开始第k + 1个数的位置。求出b数组后,如果询问区间[l, r]中的数,若b[i]大于r,说明从这个数往后的和b[i]相同的数的个数小于等于k,说明此数可取。那么问题转化为了询问[l, r]中b[i] > r的数的个数。因为只需要单点修改和区间询问,我们可以很容易想到用树套树主席树来解决这个问题。

代码:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 100010;
struct SegementTree {
	int lson, rson;
	int val;
};
SegementTree tr[maxn * 200];
int root[maxn], tot;
void pushup(int x) {
	tr[x].val = tr[tr[x].lson].val + tr[tr[x].rson].val;
}
void insert(int lnow, int rnow, int l, int r, int pos) {
	tr[rnow] = tr[lnow];
	if(l == r) {
		tr[rnow].val++;
		return;
	}
	int mid = (l + r) >> 1;
	if(pos <= mid) {
		tr[rnow].lson = ++tot;
		insert(tr[lnow].lson, tot, l, mid, pos);
	} else {
		tr[rnow].rson = ++tot;
		insert(tr[lnow].rson, tot, mid + 1, r, pos);
	}
	pushup(rnow);
}
int query(int lnow, int rnow, int l, int r, int ql, int qr) {
	if(l >= ql && r <= qr) {
		return tr[rnow].val - tr[lnow].val;
	}
	int mid = (l + r) >> 1, ans = 0;
	if(ql <= mid) ans += query(tr[lnow].lson, tr[rnow].lson, l, mid, ql, qr);
	if(qr > mid) ans += query(tr[lnow].rson, tr[rnow].rson, mid + 1, r, ql, qr);
	return ans;
}
int a[maxn], b[maxn];
vector<int> c[maxn];
int main() {
	int n, m, k, x, y;
	scanf("%d%d", &n, &k);
	for (int i = 1; i <= n; i++) {
		scanf("%d", &a[i]);
	}
	for (int i = n; i >= 1; i--) {
		if(c[a[i]].size() < k) b[i] = n + 1;
		else b[i] = c[a[i]][c[a[i]].size() - k];
		c[a[i]].push_back(i);
	}
	for (int i = 0; i <= n; i++)
		root[i] = ++tot;
	for (int i = 1; i <= n; i++)
		insert(root[i - 1], root[i], 1, n + 1, b[i]);
	scanf("%d", &m);
	int ans = 0;
	while(m--) {
		scanf("%d%d", &x, &y);
		x = ((x + ans) % n) + 1;
		y = ((y + ans) % n) + 1;
		if(x > y) swap(x, y);
		ans = query(root[x - 1], root[y], 1, n + 1, y + 1, n + 1);
		printf("%d\n", ans);
	}
}

  

原文地址:https://www.cnblogs.com/pkgunboat/p/10599335.html

时间: 2024-08-30 17:55:48

Codeforces 813E 主席树的相关文章

Educational Codeforces Round 22 E. Army Creation(主席树)

题目链接:Educational Codeforces Round 22 E. Army Creation 题意: 给你n个数和一个数k,然后有q个询问. 每个询问 有一个区间[l,r],问你这个区间内在满足每一种数不超过k的情况下,最大能选多少个数出来. 强制在线. 题解: 一看就要用到主席树,和主席数求区间内有多少不同的数的个数处理方法相同. 依次将每个数插入,当这个数出现的个数等于k了,就把最前面的那个数删掉. 然后询问就访问root[r]就行了. 第一次写完数据结构没有调试一遍过样例,一

Codeforces Round #406 (Div. 2) E. Till I Collapse(主席树)

题目链接:Codeforces Round #406 (Div. 2) E. Till I Collapse 题意: 给你n个数,对于每一个k(1<=k<=n),划分区间,每个区间只能有k个不同的数字, 问最小的划分区间的个数. 题解: 用主席树倒着将数插入,对于每个区间询问第k个不同数的位置就行了. #include<bits/stdc++.h> #define F(i,a,b) for(int i=a;i<=b;i++) #define ___ freopen("

Codeforces 464E #265 (Div. 1) E. The Classic Problem 主席树+Hash

E. The Classic Problem http://codeforces.com/problemset/problem/464/E 题意:给你一张无向带权图,求S-T的最短路,并输出路径.边权为2^xi.xi≤105,n≤105,m≤105. 想法:边权太大了,可以用数组按二进制存下来.带高精度跑太费事了. 观察一下,这里距离的更新:c=(a,b),用dis[a]更新dis[b] ①dis[b][c]=0,直接赋为1.只有一个数字改变. ②dis[b][c]=1,需要进位.考虑极端情况数

Educational Codeforces Round 22 E. Army Creation 主席树 或 分块

E. Army Creation As you might remember from our previous rounds, Vova really likes computer games. Now he is playing a strategy game known as Rage of Empires. In the game Vova can hire n different warriors; ith warrior has the type ai. Vova wants to

CodeForces 464E The Classic Problem | 呆克斯歘 主席树维护高精度

题意描述 有一个\(n\)点\(m\)边的无向图,第\(i\)条边的边权是\(2^{a_i}\).求点\(s\)到点\(t\)的最短路长度(对\(10^9 + 7\)取模). 题解 思路很简单--用主席树维护每个点的\(dis\).因为每次更新某个点\(v\)的\(dis_v\)的时候,新的\(dis_v\)都是某个点\(u\)的\(dis_u + 2^{w_{u, v}}\),相当于在原先\(u\)对应的主席树基础上修改,得到新的一棵主席树,作为\(v\)对应的主席树. 主席树(线段树)维护二

CodeForces 547E:Mike and Friends(AC自动机+DFS序+主席树)

What-The-Fatherland is a strange country! All phone numbers there are strings consisting of lowercase English letters. What is double strange that a phone number can be associated with several bears! In that country there is a rock band called CF con

Codeforces 1000F One Occurrence 主席树|| 离线+线段树

One Occurrence 为什么我半年前这么菜呀, 这种场只A三题... 我们在主席树 || 线段树上维护每个数的右边和它一样的数在哪里, 然后就变成了区间求最大值. 注意加进去的时候要把它右边一样的数的信息删掉. 我懒得离线数据就写了个主席树. #include<bits/stdc++.h> #define LL long long #define fi first #define se second #define mk make_pair #define PLL pair<LL

[CF893F]Subtree Minimum Query (主席树)

题面: 传送门:http://codeforces.com/problemset/problem/893/F 题目大意:给你一颗有根树,点有权值,问你每个节点的子树中距离其不超过k的点的权值的最小值.(边权均为1,强制在线) Solution 这题很有意思. 我们一般看到这种距离不超过k的题目,第一反应一般是建以深度为下标,以dfs序为时间轴的的主席树. 很不幸,区间最小值并不能通过减去历史状态得出某个子树的状态. 所以说,这题妙在思想的转换. 考虑以dfs序为下标,以深度为时间轴建一颗主席树.

[poj2104]可持久化线段树入门题(主席树)

解题关键:离线求区间第k小,主席树的经典裸题: 对主席树的理解:主席树维护的是一段序列中某个数字出现的次数,所以需要预先离散化,最好使用vector的erase和unique函数,很方便:如果求整段序列的第k小,我们会想到离散化二分和线段树的做法, 而主席树只是保存了序列的前缀和,排序之后,对序列的前缀分别做线段树,具有差分的性质,因此可以求任意区间的第k小,如果主席树维护索引,只需要求出某个数字在主席树中的位置,即为sort之后v中的索引:若要求第k大,建树时反向排序即可 1 #include