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 create a balanced army hiring some subset of warriors. An army is called balanced if for each type of warrior present in the game there are not more than k warriors of this type in the army. Of course, Vova wants his army to be as large as possible.

To make things more complicated, Vova has to consider q different plans of creating his army. ith plan allows him to hire only warriors whose numbers are not less than li and not greater than ri.

Help Vova to determine the largest size of a balanced army for each plan.

Be aware that the plans are given in a modified way. See input section for details.

Input

The first line contains two integers n and k (1 ≤ n, k ≤ 100000).

The second line contains n integers a1, a2, ... an (1 ≤ ai ≤ 100000).

The third line contains one integer q (1 ≤ q ≤ 100000).

Then q lines follow. ith line contains two numbers xi and yi which represent ith plan (1 ≤ xi, yi ≤ n).

You have to keep track of the answer to the last plan (let‘s call it last). In the beginning last = 0. Then to restore values of li and ri for the ith plan, you have to do the following:

  1. li = ((xi + lastmod n) + 1;
  2. ri = ((yi + lastmod n) + 1;
  3. If li > ri, swap li and ri.

Output

Print q numbers. ith number must be equal to the maximum size of a balanced army when considering ith plan.

Example

input

6 21 1 1 2 2 251 64 31 12 62 6

output

24132

Note

In the first example the real plans are:

  1. 1 2
  2. 1 6
  3. 6 6
  4. 2 4
  5. 4 6

题意:

    给出长度为n的数组和k

    要求在线询问区间[l, r]权值,  权值定义为对于所有不同元素a[i]在区间出现的次数总和;

     如果x出现次数>k, 那么按k算。

题解

   k = 1时就是 求区间不同数个数了

   k大一点,那么往前数第k个以前出现的相同的数就是多余的了;

  插好,主席树求一求

这题还可以分快写

#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define ls i<<1
#define rs ls | 1
#define mid ((ll+rr)>>1)
#define pii pair<int,int>
#define MP make_pair
typedef long long LL;
const long long INF = 1e18+1LL;
const double Pi = acos(-1.0);
const int N = 4e6+10, M = 1e3+20, mod = 1e9+7,inf = 2e9;

int n,k,a[N];
vector<int > G[N];
int l[N],r[N],v[N],sz;
void update(int x,int &y,int ll,int rr,int k,int c) {
    y = ++sz;
    v[y] = v[x] + c;
    r[y] = r[x];
    l[y] = l[x];
    if(ll == rr) return ;
    if(k <= mid)
        update(l[x],l[y],ll,mid,k,c);
    else update(r[x],r[y],mid+1,rr,k,c);
}
int query(int x,int ll,int rr,int s,int t) {
    if(s <= ll && rr <= t) return v[x];
    int ret = 0;
    if(s <= mid) ret += query(l[x],ll,mid,s,t);
    if(t > mid) ret += query(r[x],mid+1,rr,s,t);
    return ret;
}

int b[N],root[N];
int main() {
    scanf("%d%d",&n,&k);
    for(int i = 1; i <= n; ++i)scanf("%d",&a[i]);
    for(int i = 1; i <= n; ++i)G[a[i]].push_back(i);
    for(int i = 1; i <= 100000; ++i) {
        if(G[i].size() <= k) continue;
        for(int j = k; j < G[i].size(); ++j) {
            b[G[i][j]] = G[i][j-k];
        }
    }
    for(int i = 1; i <= n; ++i) {
        int xx = 0;
        if(b[i])
            update(root[i-1],xx,1,n,b[i],-1),
            update(xx,root[i],1,n,i,1);
        else update(root[i-1],root[i],1,n,i,1);

    }

    int q,last = 0;
    scanf("%d",&q);
    while(q--) {
        int x,y;
        scanf("%d%d",&x,&y);
        int L = (x + last)%n + 1;
        int R = (y + last)%n + 1;
        if(L > R) swap(L,R);
        last = query(root[R],1,n,L,R);
        printf("%d\n",last);
    }
    return 0;
}
时间: 2024-07-31 14:25:55

Educational Codeforces Round 22 E. Army Creation 主席树 或 分块的相关文章

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

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

[Educational Codeforces Round#22]

来自FallDream的博客,未经允许,请勿转载,谢谢. 晚上去clj博客逛来逛去很开心,突然同学提醒了一下,发现cf已经开始40分钟了,慌的一B,从B题开始写,写完了B到E最后收掉了A,结果太着急B题忘记写一个等号挂掉了....D题瞎dp也挂了很难受.F题还剩5分钟的时候想出来了,如果没迟应该能写完. A. 你要做n道题 每道题要花费时间ti,有m个可以提交的时间段,你在同一时刻可以交很多代码并且不耗时间,求最早什么时候可以把代码全部交完. 发现只要管最后一道题啥时候交就行了,扫一遍区间. #

【Educational Codeforces Round 22】

又打了一场EDU,感觉这场比23难多了啊-- 艹还是我太弱了. A. 随便贪心一下. #include<bits/stdc++.h> using namespace std; int n,sum=0,ans=-1,m; inline int read(){ int f=1,x=0;char ch; do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9'); do{x=x*10+ch-'0';ch=getchar();}while(

CF Educational Codeforces Round 10 D. Nested Segments 离散化+树状数组

题目链接:http://codeforces.com/problemset/problem/652/D 大意:给若干个线段,保证线段端点不重合,问每个线段内部包含了多少个线段. 方法是对所有线段的端点值离散化,按照左端点从大到小排序,顺着这个顺序处理所有线段,那么满足在它内部的线段一定是之前已经扫到过的.用树状数组判断有多少是在右端点范围内. 1 #include <iostream> 2 #include <vector> 3 #include <algorithm>

Educational Codeforces Round 6 E dfs序+线段树

题意:给出一颗有根树的构造和一开始每个点的颜色 有两种操作 1 : 给定点的子树群体涂色 2 : 求给定点的子树中有多少种颜色 比较容易想到dfs序+线段树去做 dfs序是很久以前看的bilibili上电子科技大学发的视频学习的 将一颗树通过dfs编号的方式 使每个点的子树的编号连在一起作为相连的区间 就可以配合线段树搞子树 因为以前好像听说过 线段树可以解决一种区间修改和查询区间中不同的xx个数...所以一下子就想到了... 但是我不会写线段树..只会最简单的单点修改区间查询...不会用延迟标

Educational Codeforces Round 21 G. Anthem of Berland(dp+kmp)

题目链接:Educational Codeforces Round 21 G. Anthem of Berland 题意: 给你两个字符串,第一个字符串包含问号,问号可以变成任意字符串. 问你第一个字符串最多包含多少个第二个字符串. 题解: 考虑dp[i][j],表示当前考虑到第一个串的第i位,已经匹配到第二个字符串的第j位. 这样的话复杂度为26*n*m*O(fail). fail可以用kmp进行预处理,将26个字母全部处理出来,这样复杂度就变成了26*n*m. 状态转移看代码(就是一个kmp

Educational Codeforces Round 26 D. Round Subset(dp)

题目链接:Educational Codeforces Round 26 D. Round Subset 题意: 给你n个数,让你选其中的k个数,使得这k个数的乘积的末尾的0的个数最大. 题解: 显然,末尾乘积0的个数和因子2和因子5的个数有关. 然后考虑dp[i][j]表示选i个数,当前因子5的个数为j时,能得到因子2最多的为多少. 那么对于每个数,记录一下因子2和5的个数,做一些01背包就行了. 1 #include<bits/stdc++.h> 2 #define mst(a,b) me

Educational Codeforces Round 23 F. MEX Queries(线段树)

题目链接:Educational Codeforces Round 23 F. MEX Queries 题意: 一共有n个操作. 1.  将[l,r]区间的数标记为1. 2.  将[l,r]区间的数标记为0. 3.  将[l,r]区间取反. 对每个操作,输出标记为0的最小正整数. 题解: hash后,用线段树xjb标记一下就行了. 1 #include<bits/stdc++.h> 2 #define ls l,m,rt<<1 3 #define rs m+1,r,rt<&l

Educational Codeforces Round 25 F. String Compression(kmp+dp)

题目链接:Educational Codeforces Round 25 F. String Compression 题意: 给你一个字符串,让你压缩,问压缩后最小的长度是多少. 压缩的形式为x(...)x(...)  x表示(...)这个出现的次数. 题解: 考虑dp[i]表示前i个字符压缩后的最小长度. 转移方程解释看代码,这里要用到kmp来找最小的循环节. 当然还有一种找循环节的方式就是预处理lcp,然后通过枚举循环节的方式. 这里我用的kmp找的循环节.复杂度严格n2. 1 #inclu