acwing 249
题目大意
题目意思很简单,给出一个长度为n的数组、m个查询;每个查询有 l ~ r 查询的是区间里的众数,如果数量相等输出小的那个。
这可怎么做,?
刚开始看到这道题、懵了一会、想不到怎么做;线段树没办法维护或者是我不会维护 感觉 咋咋都不行
于是看了看书上的题解,看不懂啊 只看懂了要用分块;
于是就自己想着用分块写。。。结果我很菜没写出来,(又t又wa)
于是网上找博客看,终于 a 了,
好了不说废话了hhhhhhh
题解:
分块的思想,把这些数分成一块一块 然后暴力
首先这些数1e9 如果要用数组存个数 肯定是要离散化的。
然后 离散化完呢? 既然已经把他们分块了,那么要查询的那个答案肯定是大段+小段合并得到的
于是想想怎么得到?
看看这个歪歪扭扭的图
大段是d2 小段是d1 - d2
那么这个区间的众数肯定是在d2里的众数和d1 - d2 里的所有数里的(很他妈关键我咋就想不到 )
于是得维护一个d2 的众数 也就是维护一段连续的大段的众数
这个简单暴力就好
然后 最后知道了答案在那些数里 可是怎么去找答案?
也就是要统计查询的 l ~ r 里那些数的个数。
怎么统计? for一遍肯定是不行的。
这里也是我所想不到的;
用一个vector[maxn] 二维数组 存每个数字出现的地方,于是这个数字出现的次数就是:upper_bound( vp[x].begin() , vp[x].end() , r ) - lower_bound( vp[x].begin(), vp[ x ].end() , l ) ;
这个很显然,因为vector是有序的。
附上代码:
#include<stdio.h>
#include<algorithm>
#include<set>
#include<math.h>
#include<vector>
using namespace std;
vector<int> vv;
const int maxn = 4e4+5;
const int N = 805;
vector<int> vp[maxn];
int bj[maxn];
int zs[N][N];
int a[maxn];
int L[maxn];
int R[maxn];
int vis[maxn];
int n;
int temp[maxn];
void init()
{
int t = sqrt(1.0 * n * log(n) / log(2));
int len = t ? n / t : n;
// printf("%d\n",t);
for (int i = 1; i <= t; i ++ )
{
L[i] = (i-1) * len + 1;
R[i] = i * len;
}
if(R[t] < n)
{
L[t+1] = R[t] + 1;
R[t+1] = n;
t++;
}
for (int i = 1; i <= t; i ++ )
{
for (int j = L[i]; j <= R[i]; j ++ )
{
vis[j] = i;
}
}
for (int i = 1; i <= t; i++ )
{
int ans = 0;
int sum = 0;
for (int j = L[i]; j <= n; j ++ )
{
temp[bj[j]]++;
if(sum < temp[bj[j]] || (sum == temp[bj[j]] && bj[j] < ans))
{
sum = temp[bj[j]];
ans = bj[j];
}
zs[i][vis[j]] = ans;
}
for (int j =L[i]; j <= n; j ++ )
{
temp[bj[j]] = 0;
}
}
}
set<int> ss;
int getnum(int l,int r,int x)
{
int s1 = lower_bound(vp[x].begin(),vp[x].end(),l) - vp[x].begin();
int s2 = upper_bound(vp[x].begin(),vp[x].end(),r) - vp[x].begin() - 1;
return s2 - s1 + 1;
}
int tt[maxn];
int getans(int l,int r)
{
// printf("%d %d\n",l,r);
int kk = 0;
int p = vis[l];
int q = vis[r];
if(p + 1 <= q - 1)
tt[kk++] = zs[p+1][q-1];
for (int i = l; i <= R[p]; i ++)
{
tt[kk++] = bj[i];
}
for (int i = L[q]; i <= r; i ++ )
{
tt[kk++] = bj[i];
}
int ss = unique(tt,tt+kk) - tt;
int num = 0;
int ans = 0;
for (int i = 0; i < ss; i ++ )
{
int x = tt[i];
int s = getnum(l,r,x);
// printf("%d %d\n",x,s);
if(num < s || (num == s && x < ans))
{
ans = x;
num = s;
}
}
// printf("\n");
return ans;
}
int main()
{
int m;
scanf("%d%d",&n,&m);
for (int i = 1; i <= n; i ++ )
{
scanf("%d",&a[i]);
vv.push_back(a[i]);
}
sort(vv.begin(),vv.end());
vv.erase(unique(vv.begin(),vv.end()),vv.end());
for (int i = 1; i <= n; i ++ )
{
bj[i] = lower_bound(vv.begin(),vv.end(),a[i]) - vv.begin() + 1;
}
for (int i = 1; i <= n; i ++)
{
vp[bj[i]].push_back(i);
}
init();
int x = 0;
while( m -- )
{
int l,r;
scanf("%d%d",&l,&r);
l = (l + x - 1) % n + 1;
r = (r + x - 1) % n + 1;
if(l > r)
swap(l,r);
int s = getans(l,r);
x = vv[s - 1];
printf("%d\n",x);
}
}