列表

详情


NC14897. 序列查询

描述

给你一个序列a,有m次,每次查询一个区间[l,r]。
这个区间内一共有2^(r-l+1)-1个非空子序列
一个子序列对答案的贡献是其去重后的和
求所有子序列的贡献的和%p
每次的p不一样

输入描述

第一行两个数n,m
第二行n个数表示序列a
后面m行每行三个数l,r,p表示查询区间[l,r],模数是p

输出描述

对于每个查询输出一行一个数表示答案

示例1

输入:

5 5
1 2 2 3 4
1 2 233333
2 3 333333
1 5 203
3 5 15
2 4 8

输出:

6
6
176
6
0

说明:

[1,2]中有3个子序列(1),(2),(1,2),贡献分别为1,2,3
[2,3]中有3个子序列(2),(2),(2,2),贡献分别为2,2,2
[1,5]中有31个子序列
(1),(2),(2),(3),(4),(1,2),(1,2),(1,3),(1,4),(2,2),(2,3),(2,4),(2,3),(2,4),(3,4),(1,2,2),(1,2,3),(1,2,4),(1,2,3),(1,2,4),(1,3,4),(2,2,3),(2,2,4),(2,3,4),(2,3,4),(1,2,2,3),(1,2,2,4),(1,2,3,4),(1,2,3,4),(2,2,3,4),(1,2,2,3,4)
贡献为:1,2,2,3,4,3,3,4,5,2,5,6,5,6,7,3,6,7,6,7,8,5,6,9,9,6,7,10,10,9,10
[3,5]中有7个子序列
(2),(3),(4),(2,3),(2,4),(3,4),(2,3,4)
贡献为:2,3,4,5,6,7,9
[2,4]中有7个子序列
(2),(2),(3),(2,2),(2,3),(2,3),(2,2,3)
贡献为:2,2,3,2,5,5,5

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++11(clang++ 3.9) 解法, 执行用时: 3759ms, 内存消耗: 6628K, 提交时间: 2018-08-11 08:54:08

#include <bits/stdc++.h>
using namespace std;
#define N 100100
#define ll long long

struct ques {
	int l,r,p,id;
}q[N];
int n,m,head,sz;
int num[N],pre[N],nex[N];
ll p1[N],p2[N],sum[N];

bool cmp(ques a,ques b) {
	if (a.l/sz==b.l/sz) return a.r<b.r;
	return a.l/sz<b.l/sz;
}

void erase(int x) {
	int l=pre[x],r=nex[x];
	if (l) nex[l]=r; else head=r;
	if (r) pre[r]=l;
	nex[x]=pre[x]=0;
}

void insert(int x) {
	nex[x]=head;
	pre[head]=x;
	head=x; pre[x]=0;
}

void change(int x,int f)
{
	int now=num[x];
	if (f>0)
	{
		if (now) {
			sum[now]-=x;
			if (!sum[now]) erase(now);
		}
		if (!sum[++num[x]]) insert(now+1);
		sum[num[x]]+=x;
	} else
	{
		sum[now]-=x;
		if (!sum[now]) erase(now);
		if (now-1) {
			sum[now-1]+=x;
			if (sum[now-1]==x) insert(now-1);
		}
		num[x]--;
	}
}

ll power(int x,int p) {
	return p2[x/sz]*p1[x%sz]%p;
}

int query(int p,int len) {
	p1[0]=1; for (int i=1;i<=sz;i++) p1[i]=p1[i-1]*2%p;
	p2[0]=1; for (int i=1;i<=n/sz;i++) p2[i]=p2[i-1]*p1[sz]%p;
	int ret=0;
	for (int i=head;i;i=nex[i])
		ret=(ret+sum[i]*(power(len,p)-power(len-i,p)+p)%p)%p;
	return ret;
}

int a[N],ans[N];
int main()
{
	scanf("%d%d",&n,&m); sz=sqrt(n);
	for (int i=1;i<=n;i++) scanf("%d",&a[i]);
	for (int i=1;i<=m;i++) scanf("%d%d%d",&q[i].l,&q[i].r,&q[i].p),q[i].id=i;
	sort(q+1,q+m+1,cmp);
	int l=1,r=0;
	for (int i=1;i<=m;i++)
	{
		while (l>q[i].l) change(a[--l],1);
		while (r<q[i].r) change(a[++r],1);
		while (l<q[i].l) change(a[l++],-1);
		while (r>q[i].r) change(a[r--],-1);
		ans[q[i].id]=query(q[i].p,q[i].r-q[i].l+1);
	}
	for (int i=1;i<=m;i++) printf("%d\n",ans[i]);
	return 0;
}

上一题