Codeforces 813E - Army Creation

813E - Army Creation

思路:

线段树+二分

先预处理每个点往后走k步的下标

线段树二叉树的每个节点用vector维护这些下标,给这些下标排个序

询问区间L,R,那么把下标小于等于R的位置都减掉,因为只要后面连续k个就够了

代码:

#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define pb push_back
#define ls rt<<1,l,m
#define rs rt<<1|1,m+1,r
#define mem(a,b) memset(a,b,sizeof(a))

const int N=1e5+5;
int a[N],now[N],nxt[N],pre[N],nxtk[N],ans=0;
vector<int>vc[N<<2];
void build(int rt,int l,int r){
    if(l==r){
        vc[rt].pb(nxtk[l]);
        return ;
    }
    for(int i=l;i<=r;i++)vc[rt].pb(nxtk[i]);
    sort(vc[rt].begin(),vc[rt].end());
    int m=(l+r)>>1;
    build(ls);
    build(rs);
}
void query(int L,int R,int rt,int l,int r){
    if(L<=l&&r<=R){
        int T=upper_bound(vc[rt].begin(),vc[rt].end(),R)-vc[rt].begin();
        ans-=T;
        return ;
    }
    int m=(l+r)>>1;
    if(L<=m)query(L,R,ls);
    if(R>m)query(L,R,rs);
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n,k,q,l,r;
    cin>>n>>k;
    for(int i=1;i<=n;i++)cin>>a[i];
    for(int i=1;i<N;i++)now[i]=n+1;
    nxt[n+1]=n+1;
    for(int i=n;i>=1;i--){
        nxt[i]=now[a[i]];
        pre[now[a[i]]]=i;
        now[a[i]]=i;
    }
    for(int i=1;i<=n;i++){
        if(i==now[a[i]]){
            int t=i,cnt=0;
            while(t!=n+1&&cnt<k){
                t=nxt[t];
                cnt++;
            }
            nxtk[i]=t;
        }
        else{
            nxtk[i]=nxt[nxtk[pre[i]]];
        }
    }
    cout<<endl;
    build(1,1,n);
    cin>>q;
    while(q--){
        cin>>l>>r;
        l+=ans;
        r+=ans;
        l=l%n+1;
        r=r%n+1;
        if(l>r)swap(l,r);
        ans=r-l+1;
        query(l,r,1,1,n);
        cout<<ans<<endl;
    }
    return 0;
}

原文地址:https://www.cnblogs.com/widsom/p/8524911.html

时间: 2024-10-16 09:30:58

Codeforces 813E - 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 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

Army Creation CodeForces - 813E (水题)

题意: 给定序列, 每次询问一个区间[l,r], 问[l,r]中最多能选多少个数且每种数字不超过k 相当于加强版 HH的项链, 对于一个数t, 主席树维护上k次出现的位置pre[t], 每次查询相当于求区间内pre<左端点的总数 #include <iostream> #include <queue> #define REP(i,a,n) for(int i=a;i<=n;++i) #define mid ((l+r)>>1) using namespace

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

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的数的个数.因为只需要单点修改和区间询问,我们可以很容易想到用树套树主席树来解决这个问题. 代码: #includ

[Educational Codeforces Round#22]

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

Codeforces 514 D R2D2 and Droid Army(RMQ+二分)

An army of n droids is lined up in one row. Each droid is described by m integers a1,?a2,?...,?am, where ai is the number of details of thei-th type in this droid's mechanism. R2-D2 wants to destroy the sequence of consecutive droids of maximum lengt

CodeForces 514D R2D2 and Droid Army RMQ+二分

题目链接:点击打开链接 题意:给定n m k 下面是n*m的矩阵 最多可以操作k次,每次操作可以使任意一列上所有的数 -= 1,( 0还是0) 要求得到连续最多的行数(每行里的整数都为0),输出任意一个方案(在每一列上操作的次数) 思路: 把每列单独考虑 枚举每行,二分找这行往下最多能清空的行数, RMQ维护一列的最大值. import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.PrintWr

Codeforces Round #326 (Div. 1) - C. Duff in the Army 树上倍增算法

题意:一个n个点的数, m个人住在其中的某些点上, 每个人的标号1-m, 询问u-v 路径上标号前a个人,并输出标号,a < 10. 作法, 利用倍增, ID[j][i] 表示i到i的第2^j个祖先上前10个人, 那么每次询问直接维护就好了,细节好多, 刚开始不知道怎么求ID[j][i]. 这里把2^j分成两部分, 前2^(j-1)和 后2^(j-1)个, 然后递推的维护. 感觉树链剖分也可以做, 不知道会不会TLE, 树链剖分的话 线段树的每个点维护10个值, 每次合并就行了. #includ