Codeforces 643G - Choosing Ads(线段树)
首先考虑 \(p>50\) 的时候怎么处理,也就是求一个区间的绝对众数。我们知道众数这个东西是不能用线段树直接维护的,因为对于区间 \([l,r]\) 和 \(x\in [l,r)\),区间 \([l,r]\) 的众数不一定是 \([l,x]\) 的众数或 \([x+1,r]\) 的众数。
不过此题有一个特殊之处,就是我们要求区间的绝对众数而不是区间的众数。这时候就可以用线段树维护了,因为区间 \([l,r]\) 的绝对众数一定至少是区间 \([l,x],[x+1,r]\) 中某个区间的绝对众数(提示:反证法)。
于是我们考虑这样一个思路,对于 \([l,r]\) 中的所有数组成一个可重集 \(S\),每次选择两个数 \(x,y\in S\) 且 \(x\ne y\) 并将 \(x,y\) 从 \(S\) 中删除,直到 \(S=\varnothing\) 或 \(S\) 中所有数都相同为止。不难发现在任意时刻,原区间中的绝对众数还是 \(S\) 中的绝对众数,因为对于 \([l,r]\) 中的绝对众数 \(z\),我们设其出现次数为 \(c\),若删去的两数满足 \(x\ne z\land y\ne z\),那么删去 \(x,y\) 后还剩 \(n-2\) 个数,其中 \(z\) 出现的次数为 \(c\),\(c>\lfloor\dfrac{n}{2}\rfloor>\lfloor\dfrac{n-2}{2}\rfloor\);若删去的两数满足 \(x=z\lor y=z\),那么删去 \(x,y\) 后 \(z\) 出现的次数为 \(c-1\),由 \(c>\lfloor\dfrac{n}{2}\rfloor\) 知 \(c-1>\lfloor\dfrac{n-2}{2}\rfloor\)。我们建一棵线段树,区间 \([l,r]\) 表示的节点上维护两个值 \(x,y\),\(x\) 为将 \([l,r]\) 中所有数压入 \(S\) 后对 \(S\) 进行上文所说的操作后 \(S\) 中剩余的数,如果最终 \(S=\varnothing\) 则该值为 \(0\),\(y\) 是删完后 \(x\) 的出现次数,合并两个区间 \([l,r]\) 时就将两个子区间的 \(y\) 值作比较,并令当前区间的 \(x\) 为两个子区间的 \(y\) 值较大的 \(x\),\(y\) 值为两个子区间的 \(y\) 值相减即可。
到这里你可能会有疑惑,那就是任意时刻 \(x\) 为 \(S\) 中的绝对众数并不是 \(x\) 为原区间的绝对众数的充要条件,它仅仅只是必要条件。也就是说有可能出现最终留下的数不是原区间的绝对众数。但是注意到题目中有个奇奇怪怪的条件,叫做“输出的数中可以包含错误的数,但正确的数必须包含在输出中,并且输出的数不能超过 \(\lfloor\dfrac{100}{p}\rfloor\)”,在上述算法中我们最多输出一个数,并且可以保证若 \([l,r]\) 存在绝对众数,那么其绝对众数一定被输出,故这样是符合题意。
接下来考虑原题。我们记 \(k=\lfloor\dfrac{100}{p}\rfloor\)。由于 \(p\geq 20\),一定有 \(k\leq 5\),也就是说我们最多输出 \(5\) 个数。我们还是考虑之前的算法,只不过把“每次删除 \(2\) 个数”改为“每次删除 \(k+1\) 个数”,然后用一个 std::vector<pair<int,int> > 维护该区间中的数执行上述操作后剩余的数,以及它们的出现次数。合并时候就暴力合并左右子区间的 vector,取出现次数最大的 \(k\) 个数即可。借鉴上面的分析可知输出的数仍可能包含错误的数,但正确的数一定被包含在答案中。
时间复杂度 \(nk^2\log n\),其中 \(k_{\max}=5\)
不过似乎 std::vector<pair<int,int> > 常数有亿点点大?或许是 wtcl 罢,用 std::vector<pair<int,int> > 实现的代码 TLE 50 了,故这里是用结构体实现的代码:
#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define fill0(a) memset(a,0,sizeof(a))
#define fill1(a) memset(a,-1,sizeof(a))
#define fillbig(a) memset(a,63,sizeof(a))
#define pb push_back
#define ppb pop_back
#define mp make_pair
template<typename T1,typename T2> void chkmin(T1 &x,T2 y){if(x>y) x=y;}
template<typename T1,typename T2> void chkmax(T1 &x,T2 y){if(x<y) x=y;}
typedef pair<int,int> pii;
typedef long long ll;
typedef unsigned int u32;
typedef unsigned long long u64;
namespace fastio{
#define FILE_SIZE 1<<23
char rbuf[FILE_SIZE],*p1=rbuf,*p2=rbuf,wbuf[FILE_SIZE],*p3=wbuf;
inline char getc(){return p1==p2&&(p2=(p1=rbuf)+fread(rbuf,1,FILE_SIZE,stdin),p1==p2)?-1:*p1++;}
inline void putc(char x){(*p3++=x);}
template<typename T> void read(T &x){
x=0;char c=getchar();T neg=0;
while(!isdigit(c)) neg|=!(c^'-'),c=getchar();
while(isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=getchar();
if(neg) x=(~x)+1;
}
template<typename T> void recursive_print(T x){if(!x) return;recursive_print(x/10);putc(x%10^48);}
template<typename T> void print(T x){if(!x) putc('0');if(x<0) putc('-'),x=~x+1;recursive_print(x);}
void print_final(){fwrite(wbuf,1,p3-wbuf,stdout);}
}
const int MAXN=1.5e5;
const int INF=0x3f3f3f3f;
int n,qu,p,a[MAXN+5];
struct seq{
int cnt,x[8],y[8];
seq(){cnt=0;fill0(x);fill0(y);}
};
struct node{int l,r,lz;seq v;} s[MAXN*4+5];
seq merge(seq a,seq b){
for(int i=1;i<=b.cnt;i++){
bool ok=0;
for(int j=1;j<=a.cnt;j++){
if(a.x[j]==b.x[i]){
a.y[j]+=b.y[i];
ok=1;break;
}
} if(ok) continue;
a.x[++a.cnt]=b.x[i];a.y[a.cnt]=b.y[i];int mn=INF;
if(a.cnt<=p) continue;
for(int j=1;j<=a.cnt;j++) chkmin(mn,a.y[j]);
seq c;
for(int j=1;j<=a.cnt;j++) if(a.y[j]-mn)
c.x[++c.cnt]=a.x[j],c.y[c.cnt]=a.y[j]-mn;
a=c;
} return a;
}
void pushup(int k){s[k].v=merge(s[k<<1].v,s[k<<1|1].v);}
void build(int k=1,int l=1,int r=n){
s[k].l=l;s[k].r=r;if(l==r){s[k].v.cnt=1;s[k].v.x[1]=a[l];s[k].v.y[1]=1;return;}
int mid=l+r>>1;build(k<<1,l,mid);build(k<<1|1,mid+1,r);pushup(k);
}
void pushdown(int k){
if(s[k].lz){
s[k<<1].v.cnt=1;s[k<<1].v.x[1]=s[k].lz;
s[k<<1].v.y[1]=s[k<<1].r-s[k<<1].l+1;
s[k<<1].lz=s[k].lz;
s[k<<1|1].v.cnt=1;s[k<<1|1].v.x[1]=s[k].lz;
s[k<<1|1].v.y[1]=s[k<<1|1].r-s[k<<1|1].l+1;
s[k<<1|1].lz=s[k].lz;
s[k].lz=0;
}
}
void modify(int k,int l,int r,int x){
if(l<=s[k].l&&s[k].r<=r){
s[k].v.cnt=1;s[k].v.x[1]=x;
s[k].v.y[1]=s[k].r-s[k].l+1;
s[k].lz=x;return;
} pushdown(k);int mid=s[k].l+s[k].r>>1;
if(r<=mid) modify(k<<1,l,r,x);
else if(l>mid) modify(k<<1|1,l,r,x);
else modify(k<<1,l,mid,x),modify(k<<1|1,mid+1,r,x);
pushup(k);
}
seq query(int k,int l,int r){
if(l<=s[k].l&&s[k].r<=r) return s[k].v;
int mid=s[k].l+s[k].r>>1;pushdown(k);
if(r<=mid) return query(k<<1,l,r);
else if(l>mid) return query(k<<1|1,l,r);
else return merge(query(k<<1,l,mid),query(k<<1|1,mid+1,r));
}
int main(){
scanf("%d%d%d",&n,&qu,&p);p=100/p;
for(int i=1;i<=n;i++) scanf("%d",&a[i]);build();
while(qu--){
int opt;scanf("%d",&opt);
if(opt==1){int l,r,x;scanf("%d%d%d",&l,&r,&x);modify(1,l,r,x);}
else{
int l,r;scanf("%d%d",&l,&r);seq ret=query(1,l,r);
printf("%d ",ret.cnt);for(int i=1;i<=ret.cnt;i++) printf("%d ",ret.x[i]);
printf("\n");
}
}
return 0;
}

浙公网安备 33010602011771号