带修莫队求助
查看原帖
带修莫队求助
65743
滑稽的小宫楼主2021/2/3 19:24

这题是不是不能用带修莫队?写了一发但开O2还T三个点,两个都是1.20s满时限T的

或者是我的带修出问题了?

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#define N 100010
#define ll long long
const ll p=1000000007;
int n,m;
ll an[N],sz,a[N],s2,s;
class query{
	public:
	ll l,r,t,id;
	bool operator <(query x)const{
		if(l/sz==x.l/sz){
			if(r/sz==x.r/sz)return t<x.t;
			else return r<x.r;
		}else return l<x.l;
	}
}q[N];
class changing{
	public:
	int p;
	ll v,lst;
}op[N];
void add(ll v){
	s2=(s2+v*v%p);
	s=(s+v%p)%p;
	return;
}void del(ll v){
	s2=(s2-v*v%p+p)%p;
	s=(s-v%p+p)%p;
	return;
}void Do(int k,int l,int r){
	int p=op[k].p;
	op[k].lst=a[p];
	a[p]=op[k].v;
	if(p<=r&&p>=l)del(op[k].lst),add(op[k].v);
	return;
}void Redo(int k,int l,int r){
	int p=op[k].p;
	op[k].v=a[p];
	a[p]=op[k].lst;
	if(p<=r&&p>=l)del(op[k].v),add(op[k].lst);
}ll fpow(ll a,ll x){
	if(x==0)return 1;
	ll r=fpow(a,x/2);
	if(x&1)return r*r%p*a%p;
	else return r*r%p;
}
int main(){
	freopen("data.in","r",stdin);
	freopen("my.out","w",stdout);
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
	int que=0,tm=0;
	for(int i=1;i<=m;i++){
		int c,x,y;
		scanf("%d%d%d",&c,&x,&y);
		if(c==1)op[++tm]=(changing){x,y,0};
		else q[++que]=(query){x,y,tm,que};
	}if(tm==0)tm=1;
	sz=std::pow(tm*n,0.3333);
	std::sort(q+1,q+que+1);
	int l=1,r=0,t=0;
	for(int i=1;i<=que;i++){
		while(l<q[i].l)del(a[l++]);
		while(l>q[i].l)add(a[--l]);
		while(r<q[i].r)add(a[++r]);
		while(r>q[i].r)del(a[r--]);
		while(t<q[i].t)Do(++t,l,r);
		while(t>q[i].t)Redo(t--,l,r);
		ll len=r-l+1;
		an[q[i].id]=(len*s2%p-s*s%p+p)%p*fpow(len*len%p,p-2)%p;
	}for(int i=1;i<=que;i++)printf("%lld\n",an[i]);
	return 0;
}
2021/2/3 19:24
加载中...