题目描述
给定一个序列\(a_1,a_2,\dots,a_n\),\(m\)个询问。
每个询问指定一个区间\([l,r]\),你需要输出\(a_l,a_{l+1},\dots,a_r\)这些数字里出现次数最多的数的出现次数。
输入
第一行一个整数\(T(1\leq T\leq 6)\),表示测试数据的组数。
每组数据第一行两个数\(n,m(1\leq n,m\leq 60000)\),表示序列长度与询问次数。
第二行\(n\)个整数\(a_1,a_2,\dots,a_n(0\leq a_i\leq 10^9)\)。
之后\(m\)行每行两个数\(l,r\),表示询问的区间。
本题强制在线,所以每次询问的\(l\)和\(r\)都要异或上一个询问的输出,你可以认为每组数据的第0个询问的答案是0。
输出
每组数据\(m\)行,每行一个数表示答案。
样例输入 Copy
1
3 3
3 3 3
3 3
3 3
3 3
样例输出 Copy
1
1
1
一定要注意分块的条件L+1>=R表示在同一块或者在相邻块,因为这个符号写反了调了一早上
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
#define x first
#define y second
typedef pair<int,int> PII;
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
typedef vector<string> VS;
typedef vector<int> VI;
typedef vector<vector<int>> VVI;
inline int log_2(int x) {return 31-__builtin_clz(x);}
inline int popcount(int x) {return __builtin_popcount(x);}
inline int lowbit(int x) {return x&-x;}
inline void up(int &a,int b) {if(a<b) a = b;}
vector<int> vx;
void divide(){sort(vx.begin(),vx.end());vx.erase(unique(vx.begin(),vx.end()),vx.end());}
inline int mp(int x) {return upper_bound(vx.begin(),vx.end(),x)-vx.begin();}
const int N = 60010 , B = 300;
//f[i][j]表示i块到j块的众数
int a[N],f[B][B],s[B][N],st[B],en[B],c[N];
int n,q;
inline int sum(int L,int R,int x) {return s[R][x] - s[L-1][x];}
void pre_f()
{
int m = n/B;
for(int i=0;i<=m;++i)
{
int ans = 0;
for(int j=i;j<=m;++j)
{
for(int k=st[j];k<=en[j];++k)
c[a[k]]++, up(ans,c[a[k]]);
f[i][j] = ans;
}
memset(c,0,sizeof c);
}
}
void pre_s()
{
memset(s,0,sizeof s);
int m = n/B;
for(int i=1;i<=n;++i) s[i/B][a[i]] ++;
for(int i=1;i<=m;++i)
for(int j=1;j<=n;++j)
s[i][j] += s[i-1][j];
}
int query(int l,int r)
{
int L = l/B, R = r/B;
//一定要注意此处是L+1>=R,符号不要写反了
if(L+1>=R)
{
int ans = 0;
for(int i=l;i<=r;++i) c[a[i]]++, up(ans,c[a[i]]);
for(int i=l;i<=r;++i) c[a[i]] = 0;
return ans;
}
int ans = f[L+1][R-1];
for(int i=l;i<=en[L];++i) c[a[i]]++, up(ans,c[a[i]]+sum(L+1,R-1,a[i]));
for(int i=st[R];i<=r;++i) c[a[i]]++, up(ans,c[a[i]]+sum(L+1,R-1,a[i]));
for(int i=l;i<=en[L];++i) c[a[i]] = 0;
for(int i=st[R];i<=r;++i) c[a[i]] = 0;
return ans;
}
void solve()
{
vx.clear();
memset(s,0,sizeof s);
cin>>n>>q;
for(int i=1;i<=n;++i) en[i/B] = i;
for(int i=n; i;--i) st[i/B] = i;
for(int i=1;i<=n;++i)
{
cin>>a[i];
vx.push_back(a[i]);
}
//离散化
divide();
for(int i=1;i<=n;++i) a[i] = mp(a[i]);
pre_f(), pre_s();
memset(c,0,sizeof c);
int ans = 0;
while(q--)
{
int l,r;
cin>>l>>r;
ans = query(l^ans,r^ans);
cout<<ans<<'\n';
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int T;
cin>>T;
while(T--)
{
solve();
}
}
标签:typedef,return,分块,int,leq,vx,众数,区间,inline
From: https://www.cnblogs.com/ruoye123456/p/18377654