zoukankan      html  css  js  c++  java
  • 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
    ", ans);
    	}
    }
    

      

  • 相关阅读:
    jQuery全选反选全不选
    Ubuntu安装VMware Workstation8.0.3
    ubuntu安装的软件如何启动
    ubuntu装VirtualBox遇到的问题
    你是优秀的PHP程序员吗?
    VMWare 三种工作模式(bridged、hostonly、NAT)
    最近要做的事
    090224
    2月23日 月曜日
    周五 26日
  • 原文地址:https://www.cnblogs.com/pkgunboat/p/10599335.html
Copyright © 2011-2022 走看看