线段树-Chossing Ads-分治,主元素思想,神题

Choosing Ads

问题提出

  • 给出长度为nnn的序列AAA,以及数ppp(20≤p≤10020\le p \le 10020p100)
  • QQQ次操作,两种类型
    • (1,l,r)(1,l,r)(1,l,r),区间赋值为vvv
    • (2,l,r)(2,l,r)(2,l,r),区间出现频率≥p%\ge p\%p%的数
  • n,Q≤105n,Q \le 10^5n,Q105

问题解答

非常巧妙的一道题,用到了主元素的思想.

我们先考虑一个简单的问题,如何在一个序列中找主元素(出现频次>50%\gt 50\%>50%的元素),要求O(n)O(n)O(n)的时间复杂度和O(1)O(1)O(1)的空间复杂度.

这是一个很经典的问题,我们用到的思想就是分组,主元素一组,其他元素一组,然后各组之间每次同时抵消掉111个元素,那么最后剩下的一组一定是主元素.

编程实现如下:

//算法1
int rec = a[0],cnt = 1;
for(int i = 1;i < n;++i) {if(a[i] == rec) ++cnt;else if(--cnt == 0) rec = a[i],cnt = 1;
}

如果有主元素的话,最后recrecrec表示的一定是主元素.我们把变量nnn叫做主元素recrecrec的平衡度.对于任一序列AAA,可以证明最坏情况下主元素的平衡度都至少为111.

我们再考虑一个问题.

将分别求出序列A,BA,BA,B的主元素recArec_ArecArecBrec_BrecB,以及它们的平衡度cntAcnt_AcntAcntBcnt_BcntB.

A,BA,BA,B拼成一个新的序列,那么主元素也一定是recArec_ArecArecBrec_BrecB中的其中一个.这是很显然的,证明略去.

现在我们要判定主元素到底是recArec_ArecA还是recBrec_BrecB,我们只需要将他们相互抵消即可,换句话说看谁的cntcntcnt大,谁就是.

你可以理解为这就相当于直接在ABABAB序列上跑算法1算法11,只不过序列的顺序有所改变.

这样的话,我们有了222个子序列的主元素以及平衡度,我们就可以得到该序列的主元素以及平衡度.

假设cntA&gt;cntBcnt_A &gt; cnt_BcntA>cntB主元素就是recAB=recArec_{AB} = rec_ArecAB=recA,平衡度就是cntAB=cntA−cntBcnt_{AB}=cnt_A-cnt_BcntAB=cntAcntB

这样我们就可以得到一个分治的算法,即算法2.

至此,基础知识就说完了,我们回到这道题中.

这道题要求的是≥p%\ge p\%p%的是一定要输出,因此主元素有好多个至多k=⌊100p⌋k = \lfloor \frac{100}{p} \rfloork=p100个.

我们可以根据一个序列的有kkk个主元素分为k+1k+1k+1组,其中每个主元素自己一组,然后其他元素一组.

kkk个变量记录该序列的kkk个主元素,用kkk个变量记录每个元素的平衡度,每遇到一个元素,判断kkk个位置中有没有出现过,出现过就该位置平衡度+1,否则判断有没有空位,有的话就作为一个新的主元素,平衡度设置为1.再否则的话就令所有kkk个位置的平衡度-1(相当于抵消操作),如果平衡度为0就将这个元素拿走.

刚才说的是线性扫的做法,这道题要用线段树维护,就要该进程类似算法2的做法.

这道题用平衡树来维护上述信息,然后用算法2的精髓来实现线段合并操作.

代码

By csfxjtu96, contest: VK Cup 2016 - Round 3, problem: (G) Choosing Ads, Accepted, ##include <iostream>
#include <unordered_map>
#include <cstring>
#include <algorithm>#define pr(x) std::cout << #x <<" : " << x << std::endl
#define rep(i,a,b) for(int i = a;i <= b;++i)
#define clr(x) memset(x,0,sizeof(x))typedef std::pair<int,int> pii;const int N = 150001;
struct node {int len;pii ps[5];node(){len = 0;clr(ps);}
}seg[N<<2];int tag[N<<2];
int num[N];
int n,m,p,L;pii ps[10];
int mp[N],vis[N];
inline node maintain(node &lch,node &rch) {node res = node();res.len = lch.len + rch.len;rep(i,0,L-1) {mp[lch.ps[i].first] += lch.ps[i].second;mp[rch.ps[i].first] += rch.ps[i].second;}int pc = 0;memset(ps,0,sizeof(ps));rep(i,0,L-1) {if(!vis[lch.ps[i].first]) {ps[pc++] = (pii){lch.ps[i].first,mp[lch.ps[i].first]};vis[lch.ps[i].first] = 1;}if(!vis[rch.ps[i].first]) {ps[pc++] = (pii){rch.ps[i].first,mp[rch.ps[i].first]};vis[rch.ps[i].first] = 1;}}rep(i,0,L-1) {vis[rch.ps[i].first] = vis[lch.ps[i].first] = mp[lch.ps[i].first] = mp[rch.ps[i].first] = 0;}std::sort(ps,ps+pc,[](pii &p1,pii &p2){return p1.second > p2.second;});int cc = ps[L].second;rep(i,0,L-1) {ps[i].second -= cc;res.ps[i] = ps[i];}return res;
}inline void pushdown(int o) {if(tag[o]) {tag[o<<1] = tag[o<<1|1] = tag[o];clr(seg[o<<1].ps);clr(seg[o<<1|1].ps);seg[o<<1].ps[0] = std::make_pair(tag[o],seg[o<<1].len);seg[o<<1|1].ps[0] = std::make_pair(tag[o],seg[o<<1|1].len);tag[o] = 0;}
}inline void change(int o,int l,int r,int cl,int cr,int val) {if(cl <= l && r <= cr) {tag[o] = val;clr(seg[o].ps);seg[o].ps[0] = (pii){val,r-l+1};return ;}if(r < cl || cr < l) return ;int mid = (l + r) >> 1;pushdown(o);change(o<<1,l,mid,cl,cr,val);change(o<<1|1,mid+1,r,cl,cr,val);seg[o] = maintain(seg[o<<1],seg[o<<1|1]);
}inline node query(int o,int l,int r,int ql,int qr) {if(ql <= l && r <= qr)return seg[o];if(r < ql || qr < l) return node();int mid = (l + r) >> 1;pushdown(o);node lch = query(o<<1,l,mid,ql,qr);node rch = query(o<<1|1,mid+1,r,ql,qr);node res = maintain(lch,rch);return res;
}inline void build(int o,int l,int r) {if(l == r) {seg[o] = node();seg[o].len = 1;seg[o].ps[0] = (pii){num[l],1};return ;}int mid = (l + r) >> 1;build(o<<1,l,mid);build(o<<1|1,mid+1,r);seg[o] = maintain(seg[o<<1],seg[o<<1|1]);
}int main() {std::ios::sync_with_stdio(false);std::cin >> n >> m >> p;L = 100 / p;rep(i,1,n) std::cin >> num[i];build(1,1,n);while(m--) {int tp,l,r,x;std::cin >> tp;if(tp == 1) {std::cin >> l >> r >> x;change(1,1,n,l,r,x);}else if(tp == 2) {std::cin >> l >> r;node res = query(1,1,n,l,r);int cnt = 0;rep(i,0,L-1) {if(res.ps[i].second) cnt++;}std::cout << cnt;rep(i,0,L-1) {if(res.ps[i].second) std::cout << " " << res.ps[i].first;}std::cout << std::endl;}}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/321063.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

P2679-子串【dp】

正题 题目链接:https://www.luogu.com.cn/problem/P2679 题目大意 长度为nnn的字符串AAA和长度为mmm的字符串BBB&#xff0c;要求从AAA中截取kkk个不重复的非空子串使得他们按顺序拼接起来是字符串BBB。求方案数。 解题思路 设fi,j,k,0/1f_{i,j,k,0/1}fi,j,k,0/1​表示AAA到…

【字符串】字符串

字符串 题目大意&#xff1a; 有一个字符串&#xff0c;问有子串“bear”的子串有多少个 原题&#xff1a; 题目描述 小熊有一个由小写英文字母组成的字符串s s1s2…sn。小熊想要计算s中有多少子串包含字符串“bear”&#xff0c;也就是找出满足字符串x(i, j) sisi1…sj …

.Net Core小技巧 - Swagger适配虚拟目录及二级目录

前言随着前后端分离模式与微服务架构的出现&#xff0c;Web API变得越来越重要及普遍。而后出现的网关技术&#xff0c;使开发者更倾向于使用二级/多级目录来暴露Web API&#xff0c;一是暴露的端口更少&#xff0c;方便管理&#xff1b;二是在网关中可以处理一些公共的事务&am…

线段树-Count on a Treap-神题

Count on a Treap 题目来源 Codechef Feb 2014 COT5 https://www.codechef.com/problems/COT5 问题提出 什么是Treap 是一颗二叉搜索树,每个节点拥有keykeykey属性.是一颗堆,每个节点拥有weightweightweight属性 问题 nnn次操作,三种类型,要求维护"大根Treap" …

P6834-[Cnoi2020]梦原【数学期望,树状数组】

正题 题目链接:https://www.luogu.com.cn/problem/P6834?contestId34123 题目大意 nnn个点&#xff0c;每个点i(i≠1)i(i\neq 1)i(i​1)随机连接[i−k,i−1][i-k,i-1][i−k,i−1]中的一个点。对于每个点有一个权值aia_iai​。每次可以选择一个全部都是正权值的连通块里所有…

好代码是管出来的——使用Git来管理源代码

软件开发过程中一个重要的产出就是代码&#xff0c;软件的编码过程一般是由一个团队共同完成&#xff0c;它是一个并行活动&#xff0c;为了保证代码在多人开发中能够顺利完成&#xff0c;我们需要使用代码版本控制工具来对代码进行统一存储&#xff0c;并追踪每一份代码的历史…

【DP】序列

序列 题目大意&#xff1a; 定义“好序列”为满足每一个数是上一个数的倍数的序列&#xff0c;求一个长度为K的“好序列” 原题&#xff1a; 题目描述 一个长度为k的整数序列b1&#xff0c;b2&#xff0c;…&#xff0c;bk&#xff08;1≤b1≤b2≤…≤bk≤N&#xff09;称…

线段树-楼房重建-洛谷-P4198

楼房重建 题目大意 小A的楼房外有一大片施工工地&#xff0c;工地上有N栋待建的楼房。每天&#xff0c;这片工地上的房子拆了又建、建了又拆。他经常无聊地看着窗外发呆&#xff0c;数自己能够看到多少栋房子。 为了简化问题&#xff0c;我们考虑这些事件发生在一个二维平面…

P6835-[Cnoi2020]线形生物【期望dp】

正题 题目链接:https://www.luogu.com.cn/problem/P6835?contestId34123 题目大意 n1n1n1个点&#xff0c;其中每个iii向i1i1i1连边(i≤n)(i\leq n)(i≤n)&#xff0c;然后有mmm对(u,v)(u,v)(u,v)表示uuu向vvv连边u≥vu\geq vu≥v。开始在点111&#xff0c;每次随机走一个相连…

【DP】游戏

游戏 题目大意&#xff1a; 有一个图&#xff0c;第s秒在点p会出现c个怪物&#xff08;过了这一秒就会消失&#xff09;&#xff0c;小明可以从任意一个点出发&#xff08;从第一秒开始&#xff09;&#xff0c;有m条路径&#xff08;无向&#xff09;&#xff0c;链接着两个…

定时调度系列之Quartz.Net详解

一. 背景我们在日常开发中&#xff0c;可能你会遇到这样的需求&#xff1a;"每个月的3号给用户发信息&#xff0c;提醒用户XXX "、"每天的0点需要统计前一天的考勤记录"、"每个月的1号计算上个月的库存情况"、"定时初始化数据供其它业务使用…

CF1419E-Decryption【数论,dfs】

正题 题目链接:https://www.luogu.com.cn/problem/CF1419E 题目大意 nnn的所有约数排成一个圈&#xff0c;求一个顺序使得相邻的互质的数最少。 解题思路 质因数分解后&#xff0c;我们考虑每个质因数之间填什么。对于两个质因数a,ba,ba,b。显然a∗ba*ba∗b也是nnn的约数&…

P4445 最长回文串

P4445 最长回文串 题目描述 顺序和逆序读起来完全一样的串叫做回文串。比如acbcaacbcaacbca是回文串&#xff0c;而abcabcabc不是&#xff08;abc的顺序为abcabcabc&#xff0c;逆序为cbacbacba&#xff0c;不相同&#xff09;。 输入长度为nnn的串SSS&#xff0c;求SSS的最…

RyuJIT的华丽转身

RyuJIT是作为.NET即时编译器的代号称谓&#xff0c;它是.NET运行时的基本组件之一。与此相反的是&#xff0c;Roslyn作为C#编译器&#xff0c;其编译C#代码成为IL字节码。然后&#xff0c;其再将IL字节码编译成相对于多种处理器的机器码。随着最近对dotnet/coreclr #18064的合并…

【树状数组】【dfs】树

树 题目大意&#xff1a; 有一棵树&#xff0c;当给一个点加上一个val时&#xff0c;他的儿子会减val&#xff0c;而他儿子的儿子会加上val&#xff08;-&#xff08;-val&#xff09;val&#xff09;&#xff0c;有m条指令&#xff0c;要不输出某个点的值&#xff0c;要不给…

SP1811-Longest Common Substring【SAM】

正题 题目链接:https://www.luogu.com.cn/problem/SP1811 题目大意 求两个串的最长公共子串。 解题思路 对与第一个串首先构建一个SAMSAMSAM&#xff0c;然后考虑让第二个串在上面匹配。 对于枚举的每个位置要在SAMSAMSAM上找一个节点使得它的后缀是枚举到的位置的后缀。所…

使用Nexus搭建私有Nuget仓库

前言Nuget是ASP .NET Gallery的一员&#xff0c;是免费、开源的包管理工具&#xff0c;专注于在.Net / .Net Core应用开发过程中第三方组件库的管理&#xff0c;相对于传统单纯的dll引用要方便、科学得多。其中nuget.org是最著名的Nuget公开库&#xff0c;但是企业内部开发的&a…

Wannafly挑战赛26 题解

Wannafly挑战赛26 题目连接 https://www.nowcoder.com/acm/contest/212#question A. 御坂网络 枚举圆心所在的位置,O(n)O(n)O(n) 检查即可,总时间复杂度为O(n2)O(n^2)O(n2) B. 冥土追魂 这题比较坑,我感觉题意叙述有问题,总之也是一道水题,题解略去. C. 七彩线段 题解 …

初一模拟赛总结(3.16)

成绩&#xff1a; rankrankranknamenamenamescorescorescoreT1T1T1T2T2T2T3T3T3T4T4T4111lyflyflyf210210210303030100100100000808080222hkyhkyhky190190190100100100000101010808080333fyfyfy120120120100100100000202020000444tjhtjhtjh100100100100100100000000000555wjjwj…

牛客挑战赛43C-最优公式【二分】

正题 题目链接:https://ac.nowcoder.com/acm/contest/7413/C 题目大意 给一个序列AAA&#xff0c;求两个a,ba,ba,b使得∑i1n∑j1nmax{∣Ai−a∣,∣Aj−b∣}\sum_{i1}^n\sum_{j1}^nmax\{|A_i-a|,|A_j-b|\}i1∑n​j1∑n​max{∣Ai​−a∣,∣Aj​−b∣}最小。 解题思路 因为是取…