B.ljw 养蔷薇(普通莫队)

a d d ( ) , d e l ( ) add(),del() add(),del(),维护一个 s u m sum sum,用两次快速幂即可。

然后就是离线排序的普通莫队了,在套个前缀和就是 O ( 1 ) O(1) O(1)询问了。

普通莫队,在 n , m n,m n,m同阶下,块长为 n \sqrt{n} n 的时间复杂度是 O ( n n ) O(n\sqrt{n}) O(nn )

code

// Problem: ljw 养蔷薇
// Contest: NowCoder
// URL: https://ac.nowcoder.com/acm/contest/16786/B
// Memory Limit: 262144 MB
// Time Limit: 2000 ms
// Date: 2021-05-31 16:24:59
// --------by Herio--------

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull; 
const int N=2e4+5,M=1e5+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a,b) memset(a,b,sizeof a)
#define PII pair<int,int>
#define fi first
#define se second
#define pb emplace_back
#define SZ(a) (int)a.size()
#define IOS ios::sync_with_stdio(false),cin.tie(0) 
void Print(int *a,int n){
	for(int i=1;i<n;i++)
		printf("%d ",a[i]);
	printf("%d\n",a[n]); 
}
int n,m;
int a[N],d[N],b[N],cnt[N];
int bk;
struct node{
	int l,r,id;
	bool operator<(const node &no)const{
		return b[l]==b[no.l]?r<no.r:l<no.l;
	}
}q[M];
ll sum,f[N];
ll ksm(ll a,ll n,ll m=mod){
	ll ans=a-1;
	while(n){
		if(n&1) ans=ans*a%m;
		a=a*a%m;
		n>>=1;
	}
	return ans;
}
void add(int x){
	x=a[x];
	sum=(sum-ksm(cnt[x]+1,x)+mod)%mod;
	cnt[x]++;
	sum=(sum+ksm(cnt[x]+1,x))%mod;
}
void del(int x){
	x=a[x];
	sum=(sum-ksm(cnt[x]+1,x)+mod)%mod;
	cnt[x]--;
	sum=(sum+ksm(cnt[x]+1,x))%mod;	
}
int main(){
	scanf("%d%d",&n,&m);
	bk=(int)sqrt(n);
	for(int i=1;i<=n;i++)  scanf("%d",&a[i]);
	for(int i=1;i<=n;i++){
		 scanf("%d",&d[i]);
		 b[i]=i/bk;
		 q[i].l=max(1,i-d[i]);
		 q[i].r=min(n,i+d[i]);
		 q[i].id=i;
	}
	sort(q+1,q+n+1);
	int l=1,r=0;
	for(int i=1;i<=n;i++){
		//printf("%d %d %d\n",q[i].l,q[i].r,q[i].id);
		while(q[i].r>r) add(++r);
		while(q[i].l<l) add(--l);
		while(q[i].r<r) del(r--);
		while(q[i].l>l) del(l++);
		f[q[i].id]=sum;
		//printf("sum=%lld\n",sum);
	}
	for(int i=2;i<=n;i++)
		f[i]=(f[i]+f[i-1])%mod;
	while(m--){
		scanf("%d%d",&l,&r);
		printf("%lld\n",(f[r]-f[l-1]+mod)%mod);
	}
	return 0;
}