首页 > 其他分享 >[Ynoi2015] 盼君勿忘 题解

[Ynoi2015] 盼君勿忘 题解

时间:2024-10-25 23:00:24浏览次数:4  
标签:int 题解 复杂度 Ynoi2015 sqrt 盼君 num que kl

CSP 前学习珂学,祝自己 \(while(1)\ rp++\)。


考虑求解出每种数对答案的贡献。

设 \(t=r-l+1,k_x=\sum\limits_{i=l}^r [a_i=x]\),由容斥得贡献为 \(x(2^t-2^{t-k_x})\)。

求解 \(k_x\),考虑莫队,时间复杂度为 \(O(n\sqrt n)\),这也是本题的复杂度上限。

由于 \(p\) 会变,所以不能用莫对维护 \(2^i\)。我们希望答案的计算次数级别为 \(O(\sqrt n)\),考虑根号分治:

  • 对于出现次数 \(\le \sqrt n\) 的数,我们用数组 \(num_i\) 统计,表示当前子串出现次数为 \(i\) 的数之和为多少。可以表示为: \(num_i=\sum\limits_{j=1}^{10^5}[k_j=i]\times j\),时间复杂度 \(O(\sqrt n)\)。

  • 对于出现次数 \(>\sqrt n\) 的数,我们直接维护它们的 \(k_i\)。由于这种数的个数级别为 \(O(\sqrt n)\),所以也没问题。

现在只需要考虑快速幂的问题。普通快速幂肯定是不行了,时间复杂度会多一只 \(\log\)。考虑预处理可以给到 \(O(\sqrt n)\),选择光速幂。

时间复杂度 \(O(\sqrt n)\)。

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+5;
int n,m,kl,a[N],l=1,r,ans[N];
struct que{int l,r,p,id;}q[N];
int cmp(que x,que y){
	if(x.l/kl!=y.l/kl)
		return x.l/kl<y.l/kl;
	if(x.l/kl%2) return x.r>y.r;
	return x.r<y.r;
}int pw1[N],pw2[N],p;
void init(int c){
	p=c,pw1[0]=pw2[0]=1;
	for(int i=1;i<=kl;i++)
		pw1[i]=pw1[i-1]*2%p;
	for(int i=1;i<=kl;i++)
		pw2[i]=pw2[i-1]*pw1[kl]%p;
}int kpow(int y){
	return pw1[y%kl]*pw2[y/kl]%p;
}int num[N],sum[N],vis[N],b[N],id;
void add(int x){
	sum[x]++;
	if(vis[x]) return;
	num[sum[x]-1]-=x;
	num[sum[x]]+=x;
}void del(int x){
	sum[x]--;
	if(vis[x]) return;
	num[sum[x]+1]-=x;
	num[sum[x]]+=x;
}signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	cin>>n>>m,kl=sqrt(n)+1;
	for(int i=1;i<=n;i++)
		cin>>a[i],num[a[i]]++;
	for(int i=1;i<=1e5;i++){
		if(num[i]>kl)
			b[++id]=i,vis[i]=1;
		num[i]=0;
	}for(int i=1;i<=m;i++)
		cin>>q[i].l>>q[i].r>>q[i].p,q[i].id=i;
	sort(q+1,q+m+1,cmp);
	for(int i=1;i<=m;i++){
		init(q[i].p);int ij=q[i].id;
		while(r<q[i].r) add(a[++r]);
		while(r>q[i].r) del(a[r--]);
		while(l>q[i].l) add(a[--l]);
		while(l<q[i].l) del(a[l++]);
		for(int j=1;j<=id;j++)
			ans[ij]=(ans[ij]+b[j]*(kpow(r-l+1)-kpow(r-l+1-sum[b[j]])))%p;
		for(int j=1;j<=kl;j++)
			ans[ij]=(ans[ij]+num[j]*(kpow(r-l+1)-kpow(r-l+1-j)))%p;
		ans[ij]=(ans[ij]+p)%p;
	}for(int i=1;i<=m;i++)
		cout<<ans[i]<<"\n";
	return 0;
}

标签:int,题解,复杂度,Ynoi2015,sqrt,盼君,num,que,kl
From: https://www.cnblogs.com/chang-an-22-lyh/p/18503414/ynoi2015-pan_jun_wu_wang-tj

相关文章

  • 题解:P11143 「SFMOI Round I」Strange Cake Game
    题目思路考虑贪心算法。根据题意,我们可以猜出结论,在最优状态下,小W将一直向下移动,小M一定向右移动。又因为小W是先手,所以当这块巧克力的横坐标小于等于纵坐标,即\(x\ley\)时,这块巧克力才可能归小W所有。另外,本题还有某些神秘做法可得\(20-25\)分。要特别注意的是......
  • 【题解】A. 错排问题
    递推T1题面(可从下方链接跳转看原题题面):求多少个n个数的排列,满足对于任意的i(1≤i≤n),有Ai≠i。题目传送门序言&结论:这是一道经典的题目,可以先记一下这个结论,设f[n]表示有n个数错排f[n]=(n-1)*(f[n-1]+f[n-2])推理过程:f[n]状态的设置是显然的(无需多言)边界......
  • 题解:Tokitsukaze, CSL and Stone Game
    ProblemLinkTokitsukaze,CSLandStoneGame题外话对于某些人说降绿甚至降黄,本人是很不同意的,毕竟多一道水蓝有什么不好题意翻译得很简洁,不再赘述。Solution不难发现有以下几种情况:只有两堆不等的,肯定选少的那堆,因为这样不易使得两堆相等。若两堆相等,一定破坏相等......
  • ZZJC新生训练赛第九场题解
    A题思路重点在于题目操作蕴含的奇偶数关系,一个偶数可以和一个奇数一起删除,两个奇数可以一起删除。代码#include<bits/stdc++.h>usingnamespacestd;intmain(){ios::sync_with_stdio(false);cin.tie(nullptr);intn;cin>>n;vector<int>ar(......
  • 蓝桥首场算法团队战2024.10.24 题解(1~5)
    蓝桥首场算法团队战2024.10.24题解1:不同角度【算法赛】题意:给定自然数S,需要找出一个自然数T。使得数字T>数字S并且S和T转化为字符串后,满足S的字典序>T的字典序。T一定存在,找出符合条件且字典序最小的T。输入:第一行一个整数t,表示t组测试用例。\((......
  • AT_abc195_e 题解
    思路这道题需要倒序计算。定义$dp_{i,j}=f$表示第$i$轮结束后余数为$j$,$f=1$时,Takahashi必胜,否则Aoki必胜。动态转移方程式令:$x=dp_{i,(j\times10+a_i)\bmod7}$$y=dp_{i,j\times10\bmod7}$$dp_{i-1,j}=\begin{cases}x\\operatorname{or}\y&b_i=T\x\......
  • 乒乓球题解()
    30pts考场上看到这个题时,第一反应就是全部展开man慢算诶,刚好有30分部分分可以\(O(n)\)维护那么使用\(tot\)来记录遍历到哪一位了,当\(tot\)遍历到结尾时直接让他归0即可点击查看代码#include<bits/stdc++.h>usingnamespacestd;intn,len,tot,a,b,A,B;chart[10010......
  • ♿交换序列题解♿
    以下将状态\(K\),\(E\),\(Y\)用数字0,1,2表示。考虑\(dp\)我们设\(dp[a][b][c][d]\)表示\(K\)用了\(a\)次,\(E\)用了\(b\)次,\(Y\)用了\(c\)次,总共交换了\(d\)次,前缀和$sum[i][j]$表示到第\(j\)位有几个字母\(i\)记录一个\(loc[i][j]\)表示第\(j\)个字......
  • 序列题解
    哈哈哈我也有个唐氏做法也是考虑一个朴素dp,设\(dp_{i}\)表示以\(i\)结尾的字串最长是多少,则容易想到若\(a_{i-1}\)和\(a_i\)是等比数列的一部分就一定能从\(dp_{i-1}\)转移到\(dp_i\),证明最后讲那么如何判断\(a_{i-1}\)和\(a_i\)是否为等比数列的一部分呢?首先......
  • 最长的Y题解
    考虑将Y单独拎出来,用数组存储他的下标,那么将第\(x\)个Y转移至第\(y\)个Y就需要\(a[x]-b[y]-1\)次操作。发现一个问题:第一次从左移动至\(y\)需要减1,第二次从左移动需要减2……如图:这似乎是一个很麻烦的问题,我们的某知名\(lyh\)教授是通过指针(应该是吧)解决的。......