CSP-S开小灶3 滚【分块莫队】
https://tg.hszxoj.com/contest/458/problem/2
其实我开始思路是对的,莫队维护询问的每一步操作对区间出现次数的改变,但是几个优化和关键性的地方想错了:
(1)不能用可重复集合,不然你就需要在set里跳很多次。直接cnt记录每种出现次数出现的次数就行。
(2)在寻找合法的时候,对于x,只要他的前驱合法一定合法,所以判断相邻就可以。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define _f(i,a,b) for(register int i=a;i<=b;++i)
#define f_(i,a,b) for(register int i=a;i>=b;--i)
#define chu printf
#define ll long long
#define ull unsigned long long
inline ll re()
{
ll x=0,h=1;
char ch=getchar();
while(ch<'0'||ch>'9')
{
if(ch=='-')h=-1;
ch=getchar();
}
while(ch<='9'&&ch>='0')
{
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x*h;
}
const int N=2e5+10;
int n,m;
int a[N],w[N],base,cnt[N];//cnt是出现次数,也是这个数在不在set里面
int vis[N];
set<int>s;
struct QUERY
{
int l,r,k,id;//但是这个k啊,只能O(n)扫了,
bool operator <(const QUERY&A)const
{
int code1=(r+1)/base,code2=(A.r+1)/base;
if(code1!=code2)return code1<code2;
if(code1&1)return l<A.l;
return l>A.l;
}
}q[N];
int ans[N];
set<int>::iterator it1,it2,ls;
inline void add(int pos)
{
int vl=a[pos];
if(cnt[vl])//如果set里面有出现次数
{
vis[cnt[vl]]--;
if(!vis[cnt[vl]])s.erase(cnt[vl]);//只有这一个数占据
}
cnt[vl]++;
vis[cnt[vl]]++;
if(vis[cnt[vl]]==1)s.insert(cnt[vl]);
}
inline void del(int pos)
{
int vl=a[pos];
if(cnt[vl])//如果set里有这个出现次数
{
vis[cnt[vl]]--;
if(!vis[cnt[vl]])s.erase(cnt[vl]);
}
cnt[vl]--;
if(!cnt[vl])//没有出现什么都不加了
return;
vis[cnt[vl]]++;
if(vis[cnt[vl]]==1)
s.insert(cnt[vl]);
}
int main()
{
// freopen("1.in","r",stdin);
//freopen("a.out","w",stdout);
n=re(),m=re();
_f(i,1,n)a[i]=re();
_f(i,1,n)w[i]=re();
base=sqrt(n);
_f(i,1,m)
q[i].l=re(),q[i].r=re(),q[i].k=re(),q[i].id=i;
sort(q+1,q+1+m);
int l=1,r=0;
_f(i,1,m)
{
if(q[i].r-q[i].l==0)
{
ans[q[i].id]=-1;continue;
}
while(q[i].r>r)add(++r);
while(q[i].l<l)add(--l);
while(q[i].r<r)del(r--);
while(q[i].l>l)del(l++);
int Mx=-1;
it1=s.begin(),it2=next(s.begin());
for(;it2!=s.end();++it2,++it1)
{
if((*it2)-(*it1)<=q[i].k)Mx=max(Mx,w[*it2]);
}
ans[q[i].id]=Mx;
}
_f(i,1,m)chu("%d\n",ans[i]);
return 0;
}
/*
7 3
1 3 3 2 1 3 3
1 2 3 4 5 6 7
1 7 1
3 5 1
5 7 1
2
-1
2
10 3
1 2 3 3 2 3 3 2 4 4
1 1 4 5 1 4 1 9 1 9
2 6 1
3 9 3
1 10 1
*/