zoukankan      html  css  js  c++  java
  • 题解 洛谷 P3709 【大爷的字符串题】

    luogu's link

    题意:

    这题...题意是重点!!!作为一道语文题,这道题的题意使难度上升了很多(其实重点是因为我语文差/kk

    给你一个字符串 (a) (其实不是字符串,就是一个数组),每次询问一段区间的贡献。

    区间的贡献定义:

    初始 (rp=0)

    每次从这个区间中拿出一个字符 (x) (数),然后把 (x) 从这个区间中删除,直到区间为空。你要维护一个集合 (S)

    • 如果 (S) 为空,你 (rp-1)

    • 如果 (S) 中有一个元素大于等于 (x),则你 (rp-1),清空 (S)

    • 之后将 (x) 插入 (S)

    要求使得 (rp) 最大。

    数据范围:(1 leq n,m le 2 imes10^5)

    Solution:

    由这个数据范围及只需查询很容易想到 莫队。

    题意看起来比较麻烦,我一开始也被搞蒙了,后经过大佬@快乐的疯烁及神仙同桌@子落楸枰指点,才懂。

    举个栗子:

    比如题目编号 1 2 3 4 5 6 7

    难度分别为 1 2 2 3 3 3 3

    要查询 1-4,2-5,3-6

    手摸得知,答案为 -2,-2,-3

    插入顺序:

    查询点1:以编号为 1,2,4,3 顺序插入最优。

    查询点2:以编号为 2,4,3,5 顺序插入最优。

    查询点3:以编号为 3,4,5,6 顺序插入最优。

    由此,我们可以发现两个结论:

    1. 答案正是查询区间众数(与P1997 faebdc 的烦恼一样,是双倍经验)

    2. 插入时我们并不是从左到右插的,而是先全部是不同大小的插入,所以后面查询的时候是要先改 (r),再改 (l) 的!!!(不然你会得到 (80) 的高分,我就是因为这个调了两个晚自修 /fad)。

    Code:

    代码就很简单了。

    
    /*
     * @Author: FuTianyu 
     * @Date: 2020-11-05 18:07:14 
     * @Last Modified by: FuTianyu
     * @Last Modified time: 2020-11-05 20:06:21
     */
    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    #define debug() puts("fty")
    #define FOR(i,a,b) for(int i=a;i<=b;i++)
    #define REP(i,a,b) for(int i=a;i>=b;i--)
    /*
    快读快输
    */
    const int N=2e5+5;
    int n,m,a[N],b[N],kc,kuai[N],tong[N],sum[N],ans,Ans[N];
    /*
    a_i表示原始数组,由于很大,需要离散化,b_i即为离散化后的数组.
    tong_i表示第i个数在区间内出现的个数,sum_i表示区间内出现个数为i的个数.
    */
    struct node{
        int l,r,id;
    }cun[N];
    bool cmp(node x,node y){
        return kuai[x.l]==kuai[y.l]?x.r<y.r:kuai[x.l]<kuai[y.l];
    }
    void del(int x){
        sum[tong[b[x]]]--;
        if(ans==tong[b[x]]&&sum[tong[b[x]]]==0) ans--;
        sum[--tong[b[x]]]++;
    }
    void add(int x){
        sum[tong[b[x]]]--;
        if(ans==tong[b[x]]) ans++;
        sum[++tong[b[x]]]++;
    }
    signed main(){
        n=read();
        m=read();
        kc=sqrt(n);
        FOR(i,1,n){
            a[i]=read();
            b[i]=a[i];
            kuai[i]=(i-1)/kc+1;
        }
        sort(a+1,a+1+n);
        int len=unique(a+1,a+1+n)-a-1;
        FOR(i,1,n) b[i]=lower_bound(a+1,a+1+len,b[i])-a;
        FOR(i,1,m){
            cun[i].l=read();
            cun[i].r=read();
            cun[i].id=i;
        }
        sort(cun+1,cun+1+m,cmp);
        int l=1,r=0;
        FOR(i,1,m){
            int L=cun[i].l;
            int R=cun[i].r;
            while(r>R) del(r--);
            while(r<R) add(++r);
            while(l<L) del(l++);          
            while(l>L) add(--l);              
            Ans[cun[i].id]=-ans;
        }
        FOR(i,1,m){
            write(Ans[i]);
            puts("");
        }
        return 0;
    }
    
  • 相关阅读:
    Chrome
    给Xshell增加快速命令集
    Integer对象大小比较问题
    maven的mirror和repository加载顺序
    maven的settings.xml详解
    OAuth2.0 RFC 6749 中文
    Linux下netstat命令简单操作
    Linux里的几种不同的压缩命令小记
    [ASIS 2019]Unicorn shop
    Metasploit魔鬼训练营第一章作业
  • 原文地址:https://www.cnblogs.com/F-T-Y/p/Solution-Luogu-P3709.html
Copyright © 2011-2022 走看看