luogu P2709 小B的询问 最简单的莫队

块内按右端点sort,块外按左端点sort

话说我刚开始这么修改。。。

inline void del(int i) {cnt-=(c[a[i]]*c[a[i]]),cnt+=(c[a[i]]-1)*(c[a[i]]-1),--c[a[i]];}
inline void ins(int i) {cnt-=(c[a[i]]*c[a[i]]),cnt+=(c[a[i]]+1)*(c[a[i]]+1),++c[a[i]];}

十分暴力?没事不影响复杂度。。

后来看题解发现可以改成这样

inline void del(int i) {--c[a[i]],cnt-=2*c[a[i]]+1;}
inline void ins(int i) {++c[a[i]],cnt+=2*c[a[i]]-1;}

十分简练?我数学太菜了。。。

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#define R register int
using namespace std;
inline int g() {
    R ret=0,fix=1; register char ch; while(!isdigit(ch=getchar())) fix=ch==‘-‘?-1:fix;
    do ret=ret*10+(ch^48); while(isdigit(ch=getchar())); return ret*fix;
}
int n,m,k,T,l=1,r=0;
long long cnt=0,ans[50010];
int c[50010],a[50010];
struct seg {
    int l,r,rk;
    bool operator <(const seg& y)const{return (l-1)/T==(y.l-1)/T?r<y.r:l<y.l;}
}q[50010];
inline void del(int i) {--c[a[i]],cnt-=2*c[a[i]]+1;}
inline void ins(int i) {++c[a[i]],cnt+=2*c[a[i]]-1;}
signed main() {
    n=g(),m=g(),k=g(); T=1.2*sqrt(n);
    for(R i=1;i<=n;++i) a[i]=g();
    for(R i=1;i<=m;++i) q[i].l=g(),q[i].r=g(),q[i].rk=i;
    sort(q+1,q+m+1);
    for(R i=1;i<=m;++i) {
        while(l<q[i].l) del(l++);
        while(l>q[i].l) ins(--l);
        while(r<q[i].r) ins(++r);
        while(r>q[i].r) del(r--);
        ans[q[i].rk]=cnt;
    } for(R i=1;i<=m;++i) printf("%lld\n",ans[i]);
}


2019.04.12

原文地址:https://www.cnblogs.com/Jackpei/p/10693525.html

时间: 2024-10-10 16:59:12

luogu P2709 小B的询问 最简单的莫队的相关文章

luogu 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行的整数表示第i个询问的答案. 输入输出样例 输入样例#1: 6 4 3 1 3 2 1 1 3

洛谷 P2709 小B的询问

https://www.luogu.org/problem/show?pid=2709 题目描述 小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行的整数表

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行的整数表示第i个询问的答案. 输入输出样例 输入样例#1: 6 4 3 1 3 2 1 1 3

【刷题】洛谷 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行的整数表示第i个询问的答案. 输入输出样例 输入样例#1: 6 4 3 1 3 2 1 1 3

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行的整数表示第

P2709 小B的询问 【普通莫队】

这是我的莫队入门题,我也了解到了莫队分为普通莫队以及带修莫队.顾名思义,普通莫队不需要修改区间的值,而带修莫队处理区间的值会修改的查询. 能用莫队的前提条件: 1.在知道 [l, r]中信息时,可以在 O(1)的复杂度内知道 [l - 1, r],[l + 1, r],[l, r - 1],[l, r + 1]的信息,否则复杂度会爆炸. 2.能离线处理. 莫队的时间复杂度为O(n ^ 1.5),但实际效果一定会优于这个时间复杂度. 莫队的主要操作: 1.对查询区间,以 left 来进行分块,然后

[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来获得最优的转移方式 我并不知道原理

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<

莫队算法小总结 x

莫队这东西...orz 可用于解决一类可离线且在得到区间[l,r]的答案后,能在O(1)或O(log2n)得到区间[l,r+1]或[l−1,r]的答案的问题 我们先来看这样一个问题: 给出n个数字,m次询问,每次询问在区间[li,ri]之间任选两个数字相等的概率是多少.(n,q<=50000)(小z的袜子) 在区间[l,r]中,这个概率是: ∑vi=1C(2,f(i)) ----------------- C(2,r−l+1) (v表示数字值,f(i)表示数字i在区间内出现的次数) 由于没有加和