P2709 小B的询问 莫队算法

  题意:小B有一个序列,包含N个1~K之间的整数。他一共有M个询问,每个询问给定一个区间[L..R],求Sigma(c(i)^2)的值,其中i的值从1到K,其中c(i)表示数字i在[L..R]中的重复次数。小B请你帮助他回答询问。

就是求区间不同数字个数的平方和

注意平方数可以拆开从1-n 递推。。。

#include<bits/stdc++.h>
using namespace std;
//input by bxd
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i>=(b);--i)
#define RI(n) scanf("%d",&(n))
#define RII(n,m) scanf("%d%d",&n,&m)
#define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
#define RS(s) scanf("%s",s);
#define ll long long
#define pb push_back
#define CLR(A,v)  memset(A,v,sizeof A)
//////////////////////////////////
#define inf 0x3f3f3f3f
#define lson l,m,pos<<1
#define rson m+1,r,pos<<1|1
const int N=1e5+6;

ll a[N],sum[N];
struct node
{
    ll l,r,id;
}s[N];
ll anss[N],ans,block;
bool cmp(node a,node b)
{
    return (a.l/block)==(b.l/block)?a.r<b.r:a.l<b.l;
}
void del(int x)
{
    sum[a[x]]--;
    ans-=2*sum[a[x]]+1;
}
void add(int x)
{
    sum[a[x]]++;
    ans+=2*sum[a[x]]-1;
}
int n,m,k;
int main()
{
    cin>>n>>m>>k;
    block=sqrt(n);

    rep(i,1,n)
    RI(a[i]);

    rep(i,1,m)
        scanf("%lld%lld",&s[i].l,&s[i].r),s[i].id=i;

    sort(s+1,s+1+m,cmp);
    int l=1,r=0;//指针
    rep(i,1,m)
    {
        ll L=s[i].l,R=s[i].r;//范围
        while(l<L)del(l++);
        while(r>R)del(r--);
        while(l>L)add(--l);
        while(r<R)add(++r);
        anss[s[i].id]=ans;
    }
    rep(i,1,m)
    cout<<anss[i]<<endl;

    return 0;
}

原文地址:https://www.cnblogs.com/bxd123/p/10917370.html

时间: 2024-10-05 06:57:57

P2709 小B的询问 莫队算法的相关文章

P2709 小B的询问 莫队

这个题,莫队很容易想到(格式很明显),然后直接用数学公式维护一下和就行了. 题干: 题目描述 小B有一个序列,包含N个1~K之间的整数.他一共有M个询问,每个询问给定一个区间[L..R],求Sigma(c(i)^2)的值,其中i的值从1到K,其中c(i)表示数字i在[L..R]中的重复次数.小B请你帮助他回答询问. 输入输出格式 输入格式: 第一行,三个整数N.M.K. 第二行,N个整数,表示小B的序列. 接下来的M行,每行两个整数L.R. 输出格式: M行,每行一个整数,其中第i行的整数表示第

BZOJ 3781 小B的询问 莫队算法

题目大意:一共有M个询问,每个询问给定一个区间[L..R],求Sigma(c(i)^2)的值,其中i的值从1到K,其中c(i)表示数字i在[L..R]中的重复次数. 思路:莫队走起. CODE: #include <cmath> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define MAX 50010 using namespac

[BZOJ3781][P2709]小B的询问[莫队]

入门题 对于一个区间的询问,如果在已知\([l,r]\)的答案时可以用O(1)的时间求出左右端点\(±1\)的答案,就可以使用莫队来优化. 设已知区间为\([l_1,r_1]\),所求区间为\([l_2,r_2]\) 可知求得\([l_2,r_2]\)的成本是\(|l_1-l_2| + |r_1-r_2|\)如果把这两个区间看成点,这个成本就是两点的曼哈顿距离, 对于多个询问,求出曼哈顿距离最小生成树就可以以最小成本获得答案,使用一种奇怪的方式 --sort来获得最优的转移方式 我并不知道原理

清橙A1206 小Z的袜子(莫队算法)

A1206. 小Z的袜子 时间限制:1.0s   内存限制:512.0MB 总提交次数:744   AC次数:210   平均分:44.44 将本题分享到: 查看未格式化的试题   提交   试题讨论 试题来源 2010中国国家集训队命题答辩 问题描述 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿.终于有一天,小Z再也无法忍受这恼人的找袜子过程,于是他决定听天由命-- 具体来说,小Z把这N只袜子从1到N编号,然后从编号L到R(L 尽管小Z并不在意两只袜子是不是

luoguP2709 小B的询问 [莫队]

题目描述 小B有一个序列,包含N个1~K之间的整数.他一共有M个询问,每个询问给定一个区间[L..R],求Sigma(c(i)^2)的值,其中i的值从1到K,其中c(i)表示数字i在[L..R]中的重复次数.小B请你帮助他回答询问. 输入输出格式 输入格式: 第一行,三个整数N.M.K. 第二行,N个整数,表示小B的序列. 接下来的M行,每行两个整数L.R. 输出格式: M行,每行一个整数,其中第i行的整数表示第i个询问的答案. 输入输出样例 输入样例#1: 6 4 3 1 3 2 1 1 3

【bzoj5016】[Snoi2017]一个简单的询问 莫队算法

题目描述 给你一个长度为N的序列ai,1≤i≤N和q组询问,每组询问读入l1,r1,l2,r2,需输出 get(l,r,x)表示计算区间[l,r]中,数字x出现了多少次. 输入 第一行,一个数字N,表示序列长度. 第二行,N个数字,表示a1-aN 第三行,一个数字Q,表示询问个数. 第4-Q+3行,每行四个数字l1,r1,l2,r2,表示询问. N,Q≤50000 N1≤ai≤N 1≤l1≤r1≤N 1≤l2≤r2≤N 注意:答案有可能超过int的最大值 输出 对于每组询问,输出一行一个数字,表

BZOJ 2038 小Z的袜子(莫队算法)

莫队算法如果我们已知[l,r]的答案,能在O(1)时间得到[l+1,r]的答案以及[l,r-1]的答案,即可使用莫队算法.时间复杂度为O(n^1.5).如果只能在logn的时间移动区间,则时间复杂度是O(n^1.5*log n).其实就是找一个数据结构支持插入.删除时维护当前答案. 这道题的话我们很容易用数组来实现,做到O(1)的从[l,r]转移到[l,r+1]与[l+1,r]. 那么莫队算法怎么做呢?以下都是在转移为O(1)的基础下讨论的时间复杂度.另外由于n与m同阶,就统一写n.如果已知[l

BZOJ 2038 2009国家集训队 小Z的袜子 莫队算法

题目大意:给出一些袜子的排列顺序,每次问一段区间中有多少相同颜色的袜子对. 思路:莫队算法真是一个神奇的算法.首先,暴力枚举是O(n^2)的时间复杂度,这肯定是不行的.假如区间是保证不重合的,那么就可以将总的时间转移的复杂度降到O(n).很遗憾,题目中没有这个保证.于是乎,神秘的莫队就发明了一种神奇的算法. 对于每一个询问,我们将它看成一个平面上的点(x1,y1),同样的也就会有其他的点分布在平面中.假如还有一个点(x2,y2),那么我们从第一个区间转移到第二个区间需要改变的元素总数为|x1 -

BZOJ 2038 小z的袜子 &amp; 莫队算法(不就是个暴力么..)

题意: 给一段序列,询问一个区间,求出区间中.....woc! 贴原题! 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿.终于有一天,小Z再也无法忍受这恼人的找袜子过程,于是他决定听天由命…… 具体来说,小Z把这N只袜子从1到N编号,然后从编号L到R(L 尽管小Z并不在意两只袜子是不是完整的一双,甚至不在意两只袜子是否一左一右,他却很在意袜子的颜色,毕竟穿两只不同色的袜子会很尴尬. 你的任务便是告诉小Z,他有多大的概率抽到两只颜色相同的袜子.当然,小Z希望这个概