P3709 大爷的字符串题(50分)

题目背景

在那遥远的西南有一所学校

/*被和谐部分*/

然后去参加该省省选虐场

然后某蒟蒻不会做,所以也出了一个字符串题:

题目描述

给你一个字符串a,每次询问一段区间的贡献

贡献定义:

每次从这个区间中随机拿出一个字符x,然后把x从这个区间中删除,你要维护一个集合S

如果S为空,你rp减1

如果S中有一个元素不小于x,则你rp减1,清空S

之后将x插入S

由于你是大爷,平时做过的题考试都会考到,所以每次询问你搞完这段区间的字符之后最多还有多少rp?rp初始为0

询问之间不互相影响~

输入输出格式

输入格式:

第一行两个数n,m,表示字符串长度与询问次数

之后一行n个数,表示字符串

由于你是大爷,所以字符集1e9

之后m行每行两个数,表示询问的左右区间

输出格式:

m行,每行一个数表示答案

输入输出样例

输入样例#1:

3 3
3 3 3
3 3
3 3
3 3

输出样例#1:

-1
-1
-1

说明

前4个点1s,后面的点4s

对于10%的数据,是样例

对于另外10%的数据,n,m <= 100

对于另外10%的数据,n,m <= 1000

对于另外10%的数据,n,m <= 10000

对于另外10%的数据,n,m <= 100000

对于100%的数据,n,m <= 200000

保证数据向某省省选day1T2一样sb,大家尽情用暴力水过题吧!

没事,你只要在一个好学校,就算这题只能拿到10分,也可以进队了

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<cmath>
  5 #include<cstdlib>
  6 #include<algorithm>
  7 #include<vector>
  8 #define hh 10
  9 using namespace std;
 10 const int MAXN=2000001;
 11 void read(int & n)
 12 {
 13     char c=‘+‘;int x=0;bool flag=0;
 14     while(c<‘0‘||c>‘9‘)
 15     {c=getchar();if(c==‘-‘)flag=1;}
 16     while(c>=‘0‘&&c<=‘9‘)
 17     {x=x*10+(c-48);c=getchar();}
 18     flag==1?n=-x:n=x;
 19 }
 20 int n,m;
 21 int pos[MAXN];
 22 int base;
 23 int rp=0;
 24 struct node
 25 {
 26     int l,r,id;
 27 }q[MAXN];
 28 struct dr
 29 {
 30     int a,p;
 31 }a[MAXN];
 32 int comp(const node & a,const node &b)
 33 {
 34     if(pos[a.l]==pos[b.l])
 35         return a.r<b.r;
 36     else
 37         return pos[a.l]<pos[b.l];
 38 }
 39 int cop(const dr &a,const dr &b)
 40 {
 41     return (a.a<b.a)||(a.a==b.a&&a.p<b.p);
 42 }
 43 int happen[MAXN];// 记录i出现了多少次
 44 int cnt[MAXN];// 记录出现次数为j的有多少
 45 int out[MAXN];
 46 void dele(int p)
 47 {
 48     if(rp==happen[p]&&cnt[happen[p]+hh]==1)
 49         rp--;
 50     cnt[happen[p]+hh]--;
 51     cnt[happen[p]+hh-1]++;
 52     happen[p]--;
 53 }
 54 void add(int p)
 55 {
 56     if(rp==happen[p])
 57         rp++;
 58     cnt[happen[p]+hh]--;
 59     cnt[happen[p]+hh+1]++;
 60     happen[p]++;
 61 }
 62 int ls[MAXN];
 63 void modui()
 64 {
 65     int ll=1,rr=0;
 66     for(int i=1;i<=m;i++)
 67     {
 68         for(;ll<q[i].l;ll++)
 69             dele(ls[ll]);
 70         for(;ll>q[i].l;ll--)
 71             add(ls[ll-1]);
 72         for(;rr>q[i].r;rr--)
 73             dele(ls[rr]);
 74         for(;rr<q[i].r;rr++)
 75             add(ls[rr+1]);
 76         out[q[i].id]=-rp;
 77     }
 78     for(int i=1;i<=m;i++)
 79         printf("%d\n",out[i]);
 80 }
 81 int main()
 82 {
 83     read(n);read(m);
 84     base=sqrt(n);
 85     for(int i=1;i<=n;i++)
 86         read(a[i].a),a[i].p=i;
 87     sort(a+1,a+n+1,cop);
 88     int j;
 89     for(int i=1,j=0;i<=n;i++)
 90     {
 91         if (i==1||a[i].a!=a[i-1].a) j++;
 92         ls[a[i].p]=j;
 93     }
 94     //for(int i=1;i<=n;i++)
 95 //        pos[i]=(i-1)/base+1;
 96     int sqt=0;
 97     for ( sqt=1; sqt*sqt<=n; sqt++);
 98
 99     for (int i=1; i<=n; i++) pos[i]=i/sqt;
100
101     cnt[0]=j;
102     for(int i=1;i<=m;i++)
103     {
104         read(q[i].l);
105         read(q[i].r);
106         q[i].id=i;
107     }
108     sort(q+1,q+m+1,comp);
109     modui();
110     return 0;
111 }
时间: 2024-08-04 23:01:39

P3709 大爷的字符串题(50分)的相关文章

luogu P3709 大爷的字符串题

二次联通门 : luogu P3709 大爷的字符串题 /* luogu P3709 大爷的字符串题 莫队 看了半天题目 + 题解 才弄懂了要求什么... 维护两个数组 一个记录数字i出现了几次 一个记录出现了i次的有几个数.. */ #include <algorithm> #include <cstdlib> #include <cstdio> #include <cmath> #define Max 200090 void read (int &

洛谷 P3709 大爷的字符串题

https://www.luogu.org/problem/show?pid=3709 题目背景 在那遥远的西南有一所学校 /*被和谐部分*/ 然后去参加该省省选虐场 然后某蒟蒻不会做,所以也出了一个字符串题: 题目描述 给你一个字符串a,每次询问一段区间的贡献 贡献定义: 每次从这个区间中随机拿出一个字符x,然后把x从这个区间中删除,你要维护一个集合S 如果S为空,你rp减1 如果S中有一个元素不小于x,则你rp减1,清空S 之后将x插入S 由于你是大爷,平时做过的题考试都会考到,所以每次询问

[P3709] 大爷的字符串题

Link: P3709 传送门 Solution: lxl出的语文题 其实转化一下就是求将当前区间最少拆分成多少个严格单调上升序列(可不连续) 再转化一下就是求区间内的众数个数 本来求众数的套路是主席树+二分 但此题不要求在线,用莫队同时维护$i$的出现次数$cnt[i]$和出现次数为$i$的数的个数$sum[i]$ 这样常规套路更新结果就好了 Code: #include <bits/stdc++.h> using namespace std; const int MAXN=5e5+10;

luogu P3709大爷的字符串题

lxl出的又一道毒瘤题,题目本身让人读不懂,然而实际上题面用一句话就可以总结: 给你n个数,m次询问区间[l,r]中众数的出现次数 然后就用普通的莫队就好啦~~(数据也没有那么毒瘤) #include<algorithm> #include<cmath> #include<cstdio> using namespace std; const int maxn = 200200; int pos[maxn], num[maxn]; int ans[maxn]; int f

【Luogu】P3709大爷的字符串题(莫队算法)

题目链接 语文题啊…… 看题解发现是让求区间中最多的数的个数,于是果断理解了一会题解……莫队套上完事. sum[i]表示i这个数出现的次数,cnt[i]表示出现i次的数有几个,然后乱搞搞……就好了 #include<cstdio> #include<cstdlib> #include<algorithm> #include<cstring> #include<cctype> #include<cmath> #define maxn 3

大爷的字符串题 莫队

大爷的字符串题 莫队 首先这不是一道字符串题.需要仔细研究题的性质,我们会发现答案即为区间众数的个数,因为我们可以将区间分为众数个递增数列,这样为最优. 所以问题转换为求区间众数个数.使用莫队. #include <cstdio> #include <algorithm> #include <cmath> #define MAXN 400020 using namespace std; int ans,a[MAXN],cnt[MAXN],sum[MAXN]; inlin

大爷的字符串题

莫队水毒瘤题 出题人语文水平极高,题意理解一下 就是求区间众数出现次数(什么毒瘤题目) #include <bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 5211314; int a[maxn], pos[maxn], s[maxn],d[maxn]; int cnt[maxn],ans[maxn],lx,n,m; int re(){ int x=0,w=1;char ch=getchar(

第二部分:简答题(每题5分,共50分)

第二部分:简答题(每题5分,共50分) 1.写出在DNS服务器主配置文件中配置根提示的指令块.   zone "."IN       {        type hint;        file "named.ca; };   2.简述使用代理服务器和NAT上网的区别.           3.简述查看并设置本机默认网关的步骤.    route –n   [[email protected] 桌面]# vim /etc/sysconfig/network-scripts/

jsoi r2d1t3的50分

#include<bits/stdc++.h> using namespace std; int n,r,x,y; double ans; double dis(int x,int y){return sqrt(x*x+y*y);} int main(){ cin>>n>>r; for(int i=1;i<=n;i++){cin>>x>>y;ans=max(ans,abs(dis(x,y)-r));} printf("%.10lf