首页 > 其他分享 >SP19543 GSS8 - Can you answer these queries VIII 题解

SP19543 GSS8 - Can you answer these queries VIII 题解

时间:2023-11-28 16:13:31浏览次数:47  
标签:11 SP19543 题解 sum these int ra root id

更好的阅读体验

SP19543 GSS8 - Can you answer these queries VIII

fhq + 二项式定理。提供一个不太一样的思路。默认下标从 \(1\) 开始。

首先插入删除,区间查询,想到可以平衡树维护或者离线下来做线段树。本文中是用的是 fhq,好写一些。

\(k\) 非常的小,考虑对于每一个 \(k\) 的答案如何维护。观察答案的式子:

\[ ans_k=\sum_{j=l}^ra_j(j+1-l)^k \]

因为 \(k\) 很小,可以直接把 \(k\) 次方拆开,二项式定理转化一下:

\[ \begin{aligned} ans_k&=\sum_{j=l}^ra_j(j+1-l)^k\\ &=\sum_{j=l}^ra_j\sum_{i=0}^k\binom{k}{i}(j+1)^i(-l)^{k-i}\\ &=\sum_{i=0}^k\binom{k}{i}(-l)^{k-i}\sum_{j=l}^ra_j(j+1)^i\\ \end{aligned} \]

发现我们本质需要维护的是 \(\sum a_j(j+1)^k\) 这个东西。上传的话就直接 \(\mathcal O(k)\) 暴力加。但是题目中有插入和删除操作,下标会发生平移,\(j\) 是会变的,考虑加了 \(tmp\) 以后如何维护。设 \(sum_i\) 表示 \(i\) 子树内 \(\sum a_j(j+1)^k\)。

\[ \begin{aligned} sum_k&=\sum_{j=l}^r a_j(j+1)^k\\ nsum_k&=\sum_{j=l}^r a_j(j+1+tmp)^k\\ &=\sum_{j=l}^ra_j\sum_{i=0}^k\binom{k}{i}(j+1)^itmp^{k-i}\\ &=\sum_{i=0}^k\binom{k}{i}tmp^{k-i}\sum_{j=l}^ra_j(j+1)^i\\ &=\sum_{i=0}^k\binom{k}{i}tmp^{k-i}sum_i \end{aligned} \]

直接 \(\mathcal O(k^2)\) 更新即可,需要预处理组合数和阶乘。复杂度 \(\mathcal O(mk^2\log n)\)。其实可以用 MTT 等科技优化到 \(\mathcal O(mk\log k\log n)\),但是因为 \(k\) 非常小并且 MTT 常数巨大,感觉跑的不如暴力快。理论可以用常数更小的线段树代替 fhq,但是懒得写了。。

瓶颈在于插入和删除造成区间下标的平移。

	int n,m;
	ui po[200010][11],po2[200010][11],C[11][11];
	namespace FHQ
	{
		int cnt,root;
		struct{int ls,rs,siz,tg;ui tag,val[11],sum[11];}t[200010];
		inline void update(int p){t[p].siz=t[t[p].ls].siz+t[t[p].rs].siz+1;for(int i=0;i<=10;++i)t[p].sum[i]=t[p].val[i]+t[t[p].ls].sum[i]+t[t[p].rs].sum[i];}
		inline void down(int p,int x)
		{
			t[p].tag+=x;
			if(x>0)
			{
				for(int i=10;i>=0;--i)for(int j=0;j<i;++j)t[p].sum[i]+=C[i][j]*po[x][i-j]*t[p].sum[j];
				for(int i=10;i>=0;--i)for(int j=0;j<i;++j)t[p].val[i]+=C[i][j]*po[x][i-j]*t[p].val[j];
			}
			else
			{
				for(int i=10;i>=0;--i)for(int j=0;j<i;++j)t[p].sum[i]+=C[i][j]*po2[-x][i-j]*t[p].sum[j];
				for(int i=10;i>=0;--i)for(int j=0;j<i;++j)t[p].val[i]+=C[i][j]*po2[-x][i-j]*t[p].val[j];
			}
		}
		inline void spread(int p){if(t[p].tag)down(t[p].ls,t[p].tag),down(t[p].rs,t[p].tag),t[p].tag=0;}
		void print(int p)
		{
			if(!p)return;spread(p),print(t[p].ls);
			write(p),write(t[p].ls),write(t[p].rs,'\n');
			for(int i=0;i<=10;++i)write((ll)t[p].val[i]);puts("");
			for(int i=0;i<=10;++i)write((ll)t[p].sum[i]);puts("");
			puts("");
			print(t[p].rs);
		}
		inline int newnode(int val,int id)
		{
			t[++cnt].siz=1,t[cnt].tg=rand();
			for(int i=0;i<=10;++i)t[cnt].sum[i]=t[cnt].val[i]=val*po[id+1][i];
			return cnt;
		}
		void split(int now,int k,int &x,int &y)
		{
			if(!now)return x=y=0,void();
			spread(now);
			if(k<=t[t[now].ls].siz)y=now,split(t[y].ls,k,x,t[y].ls),update(y);
			else x=now,split(t[x].rs,k-t[t[now].ls].siz-1,t[x].rs,y),update(x);
		}
		int merge(int x,int y)
		{
			if(!x||!y)return x|y;
			if(t[x].tg>t[y].tg)return spread(x),t[x].rs=merge(t[x].rs,y),update(x),x;
			return spread(y),t[y].ls=merge(x,t[y].ls),update(y),y;
		}
		int X,Y,Z;
		inline void ins(int val,int id){split(root,id,X,Y),down(Y,1),root=merge(merge(X,newnode(val,id+1)),Y);}
		inline void del(int id){split(root,id,Y,Z),split(Y,id-1,X,Y),down(Z,-1),root=merge(X,Z);}
		inline ui calc(int l,int r,int k)
		{
			split(root,r,Y,Z),split(Y,l-1,X,Y);
			int ans=0;
			for(int i=0;i<=k;++i)
			ans+=(ui)((k-i)&1?-1:1)*C[k][i]*po[l][k-i]*t[Y].sum[i];
			return root=merge(merge(X,Y),Z),ans;
		}
		inline void change(int x,int y){split(root,x,Y,Z),split(Y,x-1,X,Y);root=merge(merge(X,newnode(y,x)),Z);}
	}
	using namespace FHQ;
	inline void mian()
	{
		C[0][0]=1;
		for(int i=1;i<=10;++i)for(int j=0;j<=i;++j)C[i][j]=C[i-1][j]+(j?C[i-1][j-1]:0);
		for(int i=0;i<=200009;++i)po[i][0]=po2[i][0]=1;
		for(int i=0;i<=200009;++i)for(int j=1;j<=10;++j)po[i][j]=po[i][j-1]*i,po2[i][j]=po2[i][j-1]*(-i);
		read(n);int x,y;ll z;char ch;
		for(int i=1;i<=n;++i)read(x),root=merge(root,newnode(x,i));
		read(m);
		while(m--)
		{
			while((ch=getchar())==' ')ch=getchar();
			if(ch=='Q')read(x,y,z),write((ll)calc(x+1,y+1,z),'\n');
			else if(ch=='D')read(x),del(x+1);
			else if(ch=='I')read(x,y),ins(y,x);
			else read(x,y),change(x+1,y);
		}
	}

标签:11,SP19543,题解,sum,these,int,ra,root,id
From: https://www.cnblogs.com/WrongAnswer90-home/p/17862183.html

相关文章

  • 服务器数据库A的备份恢复到服务器B后出现问题解决
    消息10314,级别16,状态11,第2行尝试加载程序集ID65536时,Microsoft.NETFramework出错。服务器可能资源不足,或者程序集可能不受信任,PERMISSION_SET=EXTERNAL_ACCESS或UNSAFE。如上错误提示,解决办法: alterdatabasedatabasenamesettrustworthyon还有更改数据库......
  • 【题解】CF1550E Stringforces
    标签:DP\(B^+\)阅读须知:本题解较为详细地讲述的该题解法的思路和来龙去脉,但篇幅较长,请耐心阅读。Step1从题面获取信息我们考虑,因为最大值最小,所以我们首先想到二分答案。然后我们又看到\(k\leq17\)这个限制,所以会想到可能是关于一个\(2^k\)之类的复杂度。以上就是我......
  • ABC330 E Mex and Update 题解
    LinkABC330EMexandUpdateQuestion给一个数组\(a\),有\(Q\)次修改每次把\(a_i\)改成\(x\)问每次修改后,不在\(a\)数组中的最小非负数时多少Solution记录每个\(a_i\)出现的次数\(num\)每个修改操作可以看成时先删除,后添加用set维护为\(num_x=0\)的\(x\)......
  • UVA11275 3D Triangles 题解
    LinkUVA112753DTrianglesQuestion给你三维空间中的两个三角形,请判断它们是否有公共点。Solution如果在三维空间中相交,那么,肯定有一个三角形的某一条边穿过了另外一个三角形Code#include<bits/stdc++.h>usingnamespacestd;constdoubleeps=1e-9;structPoint3{......
  • SP1557 GSS2 - Can you answer these queries II 题解
    SP1557GSS2-CanyouanswerthesequeriesII更好的阅读体验扫描线。把询问挂在右端点上,扫描右端点,纵轴仍为序列维。对于这种出现多次的数只算一次的,记\(pre_i\)表示\(i\)这个值上一次的出现位置,套路化的可以强制让出现多次的在\(pre_i<l\wedgei\)统计,用二维线段树状......
  • CF1900 D Small GCD 题解
    LinkCF1900DSmallGCDQuestion定义\(f(x,y,z)=\gcd(a,b)\),其中\(a,b\)为\(x,y,z\)中较小的那两个数给出数组\(a\),求\[\sum\limits_{i=1}^n\sum\limits_{j=i+1}^n\sum\limits_{k=j+1}^nf(a_i,a_j,a_k)\]三个求和符号本质上就是选数组\(a\)中的三个数,也就是说,数......
  • P3375 【模板】KMP( 普及/提高− ) 题解
    题目传送门思路:首先我们要学习一下\(KMP\)算法,不会的可以看这个大佬的文章那么我们就直接开始讲思路了。针对于每一位,\(kmp\)算法已经预处理出了一个对应\(kmp\)数组的单元,映射着如果此位失配,它可能的最靠后的一个重新开头是哪一个。让我们举一个例子:假如让\(aaab\)与......
  • P9447 [ICPC2021 WF] Spider Walk 题解
    更好的阅读体验很有意思的一道题。设\(f_i\)表示第\(i\)根线的答案,首先有一个关键结论:任意两根相邻的线答案只差一定小于\(1\)。原因显然,可以在无限远的地方加一根线来构造。该结论可以扩展一下,对于距离为\(d\)的两根线,答案之差不会超过\(d\)。考虑进行倒着加线,考虑加......
  • CF1900 C Anji's Binary Tree 题解
    LinkCF1900CAnji'sBinaryTreeQuestion给出一个树,每个节点上有一个字母L/R/U,从\(1\)号根节点开始,L表示接下来走到左节点,R表示接下来走到右节点,U表示接下载走到父节点问,最少修改几个节点上的字母使得从根节点走到叶子节点Solution定义\(F_x\)表示从\(x\)走到叶......
  • P7626 [COCI2011-2012#1] MATRIX( 普及/提高− ) 题解
    题目传送门思路:首先思考暴力,\(O(n^4)\)的时间复杂度,不行。那么我们这里就要运用到一点前缀和的知识了。我们可以用前缀和对两条对角线进行计数。每个点有两个对角线运算。差不多是\(O(n^2)\)到\(O(n^3)\)的时间复杂度。而\(n\leq400\)稳过。Code:#include<bits/stdc......