莫队+数组低级化的 优先队列
题目:
view
3s 512M 【题目表述】 某天醒来,koishi发现自己变成了一支彩笔。并且他站在一排彩笔之中。 一开始每支彩笔的彩笔程度都为1。如果有两支彩笔颜色相同,那么他们就能合二为一,并且彩笔程度相加。 现在koishi想知道,从第l支彩笔到第r支彩笔,最多能有多大的彩笔程度。 【输入格式】 第一行为彩笔数量n和询问次数q 第二行为n个这个整数,每个整数代表这个彩笔的颜色 接下来q行,每行两个整数l和r 【输出格式】 共q行,每行一个整数,表示最大的彩笔程度 【样例输入】 6 2 1 3 2 3 3 2 1 6 2 4 【样例输出】 3 2 【数据范围与提示】 1<=n,q<=3*1e5 1<=彩笔颜色<=n 1<=l<=r<=n 对于样例的第一个询问,颜色为1的彩笔程度为1,颜色为2的彩笔程度为2,3的彩笔程度为3,因此彩笔程度最大为3。 对于第二个询问,颜色为2的彩笔程度为1,颜色为3的彩笔程度为2,因此彩笔程度最大为2。
代码:
#include <bits/stdc++.h> using namespace std; #define M 300010 #define ri register int template <class G>void read(G &x) { x=0;int f=0;char ch=getchar(); while(ch<'0'||ch>'9'){f|=(ch=='-');ch=getchar();} while(ch<='9'&&ch>='0'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} x=f?-x:x; return; } struct dian { int l,r,pos,id; bool operator <(const dian &t)const { if(pos==t.pos&&r==t.r) return l<t.l; if(pos==t.pos) return r<t.r; return pos<t.pos; } }p[M]; int val[M]; int n,m; int mx,cur; int num[M],cc[M]; struct cmp{ bool operator ()(const int a,const int b)const { return num[a]<num[b]; } }; priority_queue<int,vector<int>,cmp> q; void work(int a,int b) { cc[num[val[a]]]--; num[val[a]]+=b; cc[num[val[a]]]++; if(mx<num[val[a]]) mx=num[val[a]]; if(cc[mx]==0) mx--; } int ans[M]; void solvee() { sort(p+1,p+1+m); int l=1,r=0; // ATTENTION for(ri i=1;i<=m;i++) { while(l<p[i].l) work(l++,-1); while(l>p[i].l) work(--l,1); while(r<p[i].r) work(++r,1); while(r>p[i].r) work(r--,-1); ans[p[i].id]=mx; } } int main(){ freopen("D:\\学习\\C++\\swjtu比赛\\2021校赛决赛文档\\彩笔程度\\data\\asmall_lb_ri_4.in","r",stdin); read(n);read(m); for(ri i=1;i<=n;i++) read(val[i]); int k=int(sqrt(n)+0.5); for(ri i=1;i<=m;i++) { read(p[i].l); read(p[i].r); p[i].pos=p[i].l/k; p[i].id=i; } solvee(); for(ri i=1;i<=m;i++) printf("%d\n",ans[i]); }
思维: 1 在用一个数组来表示 每一个数量有多少个数量,哈哈哈哈 喵喵喵
2 优先队列,不适用 ,去死吧