CF1514D Cut and Stick 题解
前置知识
解法
若区间内不存在绝对众数,直接保持这一段即可。
若存在绝对众数,贪心地想肯定要尽可能地把其分开还要限制出其他数使其不成为绝对众数。容易发现设绝对众数出现次数为 \(cnt\),取 \(cnt-1\) 个其他数和绝对众数配对最优。但可能其他数不够 \(cnt\) 个,就只能让多余的绝对众数各成一组了。最终答案即为 \(2cnt-(r-l+1)\)。
主席树求下是否存在绝对众数及其出现次数即可。
代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define sort stable_sort
#define endl '\n'
int a[300010];
struct PDS_SMT
{
int root[300010],rt_sum;
struct SegmentTree
{
int ls,rs,sum;
}tree[300010<<5];
#define lson(rt) tree[rt].ls
#define rson(rt) tree[rt].rs
int build_rt()
{
rt_sum++;
return rt_sum;
}
void build_tree(int &rt,int l,int r)
{
rt=build_rt();
if(l==r)
{
return;
}
int mid=(l+r)/2;
build_tree(lson(rt),l,mid);
build_tree(rson(rt),mid+1,r);
}
void update(int pre,int &rt,int l,int r,int pos)
{
rt=build_rt();
tree[rt]=tree[pre];
tree[rt].sum++;
if(l==r)
{
return;
}
int mid=(l+r)/2;
if(pos<=mid)
{
update(lson(pre),lson(rt),l,mid,pos);
}
else
{
update(rson(pre),rson(rt),mid+1,r,pos);
}
}
int query(int rt1,int rt2,int l,int r,int k)
{
if(l==r)
{
return tree[rt2].sum-tree[rt1].sum;
}
int mid=(l+r)/2;
if(tree[lson(rt2)].sum-tree[lson(rt1)].sum>k)
{
return query(lson(rt1),lson(rt2),l,mid,k);
}
if(tree[rson(rt2)].sum-tree[rson(rt1)].sum>k)
{
return query(rson(rt1),rson(rt2),mid+1,r,k);
}
return 0;
}
}T;
int main()
{
int n,m,l,r,cnt,i;
scanf("%d%d",&n,&m);
T.build_tree(T.root[0],1,n);
for(i=1;i<=n;i++)
{
scanf("%d",&a[i]);
T.update(T.root[i-1],T.root[i],1,n,a[i]);
}
for(i=1;i<=m;i++)
{
scanf("%d%d",&l,&r);
cnt=T.query(T.root[l-1],T.root[r],1,n,(r-l+1)/2.0);
if(cnt==0)
{
printf("1\n");
}
else
{
printf("%d\n",2*cnt-(r-l+1));
}
}
return 0;
}
本文来自博客园,作者:hzoi_Shadow,原文链接:https://www.cnblogs.com/The-Shadow-Dragon/p/18377052,未经允许严禁转载。
版权声明:本作品采用 「署名-非商业性使用-相同方式共享 4.0 国际」许可协议(CC BY-NC-SA 4.0) 进行许可。