洛谷P5072 [YNOI2015]盼君勿忘 莫队+unordered_set+毒瘤卡常

2024-03-30 02:48

本文主要是介绍洛谷P5072 [YNOI2015]盼君勿忘 莫队+unordered_set+毒瘤卡常,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在太阳西斜的这个世界里,置身天上之森。等这场战争结束之后,不归之人与望眼欲穿的众人, 人人本着正义之名,长存不灭的过去、逐渐消逝的未来。我回来了,纵使日薄西山,即便看不到未来,此时此刻的光辉,盼君勿忘。————世界上最幸福的女孩

珂朵莉最可爱了,珂朵莉的题最毒瘤了qwq

题目链接:传送门

这是一个自带大常数选手被毒瘤 l x l lxl lxl卡常数,从开 O 2 O2 O2 82 82 82分到不开 O 2 O2 O2就珂 A C AC AC的故事……

先上图QWQ

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

解题思路

一开始没看懂题……“子序列”是不需要连续的……
序列上一段区间内的问题,不带修改, n ≤ 100000 n\leq 100000 n100000又是YNOI的题,容易想到莫队。
发现每次大力去重显然复杂度爆炸,又因为 a i &lt; = 1 0 5 a_i&lt;=10^5 ai<=105,因此考虑每个数对答案的贡献。
考虑区间 [ l , r ] [l,r] [l,r]。显然这个区间的子序列总数为 2 r − l + 1 2^{r-l+1} 2rl+1
假设一个数 x x x在区间 [ l , r ] [l,r] [l,r]中出现了 k k k次,那么不含 x x x的子序列总个数为 2 r − l + 1 − k 2^{r-l+1-k} 2rl+1k
所以 x x x对答案的贡献为 x ∗ ( 2 r − l + 1 − 2 r − l + 1 − k ) x*(2^{r-l+1}-2^{r-l+1-k}) x(2rl+12rl+1k)
发现大莉统计答案也会爆,所以开一个set(这里为了减小复杂度,用了unordered_set)来保存所有出现过的出现过的次数。
也就是说,比如若 [ l , r ] [l,r] [l,r]中有一个数出现了 1 1 1次,有一个数出现了 3 3 3次,那么 s e t set set里就保存了 1 , 3. 1,3. 1,3.
然后每次就珂以大莉莫队,修改在set上乱改一波,询问大莉统计就珂以了qwq
时间复杂度 O ( m n l o g n ) O(m\sqrt{n}logn) O(mn logn) (莫队 O ( m n ) O(m\sqrt{n}) O(mn ),快速幂 O ( l o g n ) O(logn) O(logn)
……
…………
………………
TLE???
掐指一算, m ∗ n ∗ l o g n m*\sqrt{n}*logn mn logn差不多为 1 0 5 ∗ 300 ∗ 16 = 4.8 ∗ 1 0 8 10^5*300*16=4.8*10^8 10530016=4.8108……
珂能其他题卡一卡就过去了,但是毒瘤的YNOI题肯定是不会放过这种错误时间复杂度过的qwq
于是考虑优化。

优化过程

首先把 n \sqrt n n 优化掉不太现实(不然lxl就不会把n,m只开到1e5),因为莫队必然会带 n \sqrt n n 的复杂度qwq。
所以考虑把快速幂的 log ⁡ n \log n logn的复杂度去掉(以下想法参考这个题解):
发现如果把 2 1 , 2 2 , 2 3 , . . . , 2 n − 1 2^1,2^2,2^3,...,2^{\sqrt n-1} 21,22,23,...,2n 1 2 n , 2 2 n , . . . , 2 n 2^{\sqrt n},2^{2\sqrt n},...,2^n 2n ,22n ,...,2n预处理出来,
就珂以把一个 2 x 2^x 2x表示成 2 k n ∗ 2 q 2^{k\sqrt n}*2^q 2kn 2q,然后 O ( 1 ) O(1) O(1)求。这里 k = x / n , q = x k=x/\sqrt{n},q=x k=x/n ,q=x m o d mod mod n \sqrt n n
于是大莉写一波啊qwq
时间复杂度 O ( m n ) O(m\sqrt{n}) O(mn )
……
…………
………………
TLE?????
笑容逐渐消失.jpg
发现总是有几个点过不去……时间复杂度应该已经最优了……于是又要卡一波常数……

卡常技巧

1. 1. 1.快读快写、 r e g i s t e r register register i n l i n e inline inline(对于像我这样的大常数选手来说,这是必备的qwq)

2. 2. 2.莫队的奇偶性玄学优化(参考这篇博客qwq)

3. 3. 3.减少取模次数:
假设 p w 1 [ i ] pw1[i] pw1[i]表示 2 i 2^i 2i,那么原本写的是:

pw1[i]=(pw1[i-1]<<1)%mod;

要改成:

pw1[i]=(pw1[i-1]<<1)<mod?pw1[i-1]<<1:(pw1[i-1]<<1)-mod;

实测这样珂以很有效地减小常数

4. 4. 4.减小除法与取模次数:
发现算 2 2 2的幂时还是要重复算很多次除法和取模,这里珂以把 i n \frac{i}{\sqrt n} n i i i i m o d mod mod n \sqrt n n 都预处理出来,然后直接调用qwq。
这样也珂以大减一波常数qwq

5. 5. 5. + + r ++r ++r l − − l-- l之类的东西和附近的操作合并一下,比如 a [ + + r ] a[++r] a[++r] a [ l − − ] a[l--] a[l]

提交……
终于过了QWQ
索然无味……

毒瘤代码

#include<stdio.h>
#include<cstring>
#include<algorithm>
#include<math.h>
#include<unordered_set>
#define re register int
using namespace std;
typedef long long ll;
typedef unordered_set<int>::iterator svi;
inline char getc() {    //优化的getchar static char buf[262145],*fs,*ft;return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<18,stdin)),fs==ft)?EOF:*fs++;
}
int read() {re x=0,f=1;char ch=getc();while(ch<'0' || ch>'9') {if(ch=='-')	f=-1;ch=getc();}while(ch>='0' && ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getc();}return x*f;
}
inline void write(int x) {if(x>9)	write(x/10);putchar(x%10+'0');
}
const int Size=100005;
int n,m,siz,a[Size],belong[Size];
struct Query {int id,l,r,p;
} Q[Size];
inline bool comp(Query x,Query y) {if(belong[x.l]!=belong[y.l])	return x.l<y.l;if(belong[x.l]&1)	return x.r<y.r;return x.r>y.r;
}
ll pw1[Size],pw2[Size];
int MOD[Size],DIV[Size];
inline ll fastpow(int n,int mod) {//算 2^n %mod 的值 return pw1[MOD[n]]*pw2[DIV[n]]%mod;
}
int vis[Size],val[Size],ans[Size];
unordered_set<int> Union;
void add(int x) {if(vis[x]) {val[vis[x]]-=x;if(!val[vis[x]]) {Union.erase(vis[x]);}}if(!val[++vis[x]])	Union.insert(vis[x]);val[vis[x]]+=x;
}
void del(int x) {val[vis[x]]-=x;if(!val[vis[x]])	Union.erase(vis[x]);if(--vis[x]) {if(!val[vis[x]]) {Union.insert(vis[x]);}val[vis[x]]+=x;}
}
int main() {n=read();m=read();//发现siz好像取m/sqrt(n)时常数小一点 //这里取sqrt(n)好像也是珂以的qwq siz=m/sqrt(n);for(re i=1; i<=n; i++) {//预处理出i/siz和i%siz的值 MOD[i]=i%siz;DIV[i]=i/siz;}for(re i=1; i<=n; i++) {a[i]=read();belong[i]=i/siz+1;}for(re i=1; i<=m; i++) {Q[i].l=read();Q[i].r=read();Q[i].p=read();Q[i].id=i;}sort(Q+1,Q+1+m,comp);pw1[0]=pw2[0]=1;int l=1,r=0;for(int i=1; i<=m; i++) {while(r<Q[i].r)	add(a[++r]);while(r>Q[i].r)	del(a[r--]);while(l<Q[i].l)	del(a[l++]);while(l>Q[i].l)	add(a[--l]);int mod=Q[i].p;//每次暴力O(sqrt(n))预处理2的幂 for(re i=1; i<=siz; i++) {
//			pw1[i]=(pw1[i-1]<<1)%mod;pw1[i]=(pw1[i-1]<<1)<mod?pw1[i-1]<<1:(pw1[i-1]<<1)-mod;}pw2[1]=pw1[siz];for(re i=2; i<=siz; i++) {pw2[i]=pw2[i-1]*pw2[1]%mod;}int len=Q[i].r-Q[i].l+1;re sum=0;for(svi it=Union.begin(); it!=Union.end(); it++) {//恶臭无比 sum=(sum+val[*it]*(fastpow(len,mod)-fastpow(len-(*it),mod)+mod))%mod;}ans[Q[i].id]=sum;}for(re i=1; i<=m; i++) {write(ans[i]);putchar(10);}return 0;
}

这篇关于洛谷P5072 [YNOI2015]盼君勿忘 莫队+unordered_set+毒瘤卡常的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/860297

相关文章

poj 3050 dfs + set的妙用

题意: 给一个5x5的矩阵,求由多少个由连续6个元素组成的不一样的字符的个数。 解析: dfs + set去重搞定。 代码: #include <iostream>#include <cstdio>#include <set>#include <cstdlib>#include <algorithm>#include <cstring>#include <cm

Collection List Set Map的区别和联系

Collection List Set Map的区别和联系 这些都代表了Java中的集合,这里主要从其元素是否有序,是否可重复来进行区别记忆,以便恰当地使用,当然还存在同步方面的差异,见上一篇相关文章。 有序否 允许元素重复否 Collection 否 是 List 是 是 Set AbstractSet 否

论文翻译:ICLR-2024 PROVING TEST SET CONTAMINATION IN BLACK BOX LANGUAGE MODELS

PROVING TEST SET CONTAMINATION IN BLACK BOX LANGUAGE MODELS https://openreview.net/forum?id=KS8mIvetg2 验证测试集污染在黑盒语言模型中 文章目录 验证测试集污染在黑盒语言模型中摘要1 引言 摘要 大型语言模型是在大量互联网数据上训练的,这引发了人们的担忧和猜测,即它们可能已

多路转接之select(fd_set介绍,参数详细介绍),实现非阻塞式网络通信

目录 多路转接之select 引入 介绍 fd_set 函数原型 nfds readfds / writefds / exceptfds readfds  总结  fd_set操作接口  timeout timevalue 结构体 传入值 返回值 代码 注意点 -- 调用函数 select的参数填充  获取新连接 注意点 -- 通信时的调用函数 添加新fd到

Android set Tag, findViewWithTag使用

设置了tag为“principal”的view ImageView principal = (ImageView) findViewById(R.id.imagen_home_0);principal.setTag("principal"); 在其它地方获取,获取已经设置了tag为“principal”的view LayoutInflater inflater = LayoutInflate

C++ STL关联容器Set与集合论入门

1. 简介 Set(集合)属于关联式容器,也是STL中最实用的容器,关联式容器依据特定的排序准则,自动为其元素排序。Set集合的底层使用一颗红黑树,其属于一种非线性的数据结构,每一次插入数据都会自动进行排序,注意,不是需要排序时再排序,而是每一次插入数据的时候其都会自动进行排序。因此,Set中的元素总是顺序的。 Set的性质有:数据自动进行排序且数据唯一,是一种集合元素,允许进行数学上的集合相

Eclipse或MyEclipse中Java Working Set管理项目

随着学习JAVA的时间的越来越久,项目也越来越多,Eclipse或MyEclipse界面中显示一堆! 每次工作使用到的项目肯定不会太多...... 每次从这么大数量的工程当中找到自己要使用的, 必须大规模的滚动滚动条...... 图片一   Project Explorer中:    图片二:Package Explorer中: 这样就好找很多了,分类放!

高精度计算(代码加解析,洛谷p1601,p1303)除法待更新

目录 高精度加法 高精度减法 高精度乘法 高精度加法 我们知道在c++语言中任何数据类型都有一定的表示范围。当两个被加数很大时,正常加法不能得到精确解。在小学,我们做加法都采用竖式方法。那么我们也只需要按照加法进位的方式就能得到最终解。 8 5 6+ 2 5 5-------1 1 1 1 加法进位: c[i] = a[i] + b[i];if(c[i] >=

STL set整理

#include<set>#include<cstdio>#include<iterator>#include<iostream>#include<algorithm>using namespace std;//set 集合的操作//multisetset<int>Set1;set<int>Set2;set<int>Set3;/*begin() 返回指向第一个元素的迭代器

解决PHP Warning: strftime(): It is not safe to rely on the system's timezone set

当运行一些程序时,在httpd日志中会有如下警告日志: PHP Warning:  strftime(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set(