「SNOI2017」一个简单的询问

简单的解法

显然可以差分一下。

\[get(l,r,x)\times get(l1,r1,x)=get(1,r,x) \times get(1,r1,x)-get(1,l-1,x) \times get(1,r1,x)-get(1,r,x) \times get(1,l1-1,x)+get(1,l-1,x) \times get(1,l1-1,x)
\]

因为都是1为起始,那么记两个cnt数组,表示前缀,然后可以分成四个区间,莫队。

#include <bits/stdc++.h>
#define rep(q, a, b) for (int q = a, q##_end_ = b; q <= q##_end_; ++q)
#define dep(q, a, b) for (int q = a, q##_end_ = b; q >= q##_end_; --q)
#define mem(a, b) memset(a, b, sizeof a)
#define debug(a) cerr << #a << ' ' << a << "___" << endl
using namespace std;
bool cur1;
char buf[10000000], *p1 = buf, *p2 = buf;
#define Getchar() p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 10000000, stdin), p1 == p2) ? EOF : *p1++
void in(int &r) {
static char c;
r = 0;
while (c = Getchar(), c < 48)
;
do
r = (r << 1) + (r << 3) + (c ^ 48);
while (c = Getchar(), c > 47);
}
const int mn = 50005;
int K, n, val[mn];
long long ans[mn];
struct node {
int l, r, id, ty;
bool operator<(const node &A) const {
return l / K == A.l / K ? (l / K & 1 ? r > A.r : r < A.r) : l / K < A.l / K;
}
} an[mn * 4];
int cnt[mn], cnt1[mn];
long long mid_ans;
bool cur2;
int main() {
// cerr<<(&cur2-&cur1)/1024.0/1024<<endl;
in(n);
K = sqrt(n) + 1;
rep(q, 1, n) in(val[q]);
int Q;
in(Q);
int l, r, l1, r1;
int ct = 0;
rep(q, 1, Q) {
in(l), in(r), in(l1), in(r1);
an[++ct] = { r, r1, q, 1 };
if (l > 1) {
an[++ct] = { l - 1, r1, q, -1 };
if (l1 > 1)
an[++ct] = { l1 - 1, l - 1, q, 1 };
}
if (l1 > 1)
an[++ct] = { l1 - 1, r, q, -1 };
}
sort(an + 1, an + ct + 1);
l = 0, r = 0;
rep(q, 1, ct) {
while (l > an[q].l) mid_ans -= cnt1[val[l]], --cnt[val[l--]];
while (r < an[q].r) mid_ans += cnt[val[++r]], ++cnt1[val[r]];
while (l < an[q].l) mid_ans += cnt1[val[++l]], ++cnt[val[l]];
while (r > an[q].r) mid_ans -= cnt[val[r]], --cnt1[val[r--]];
ans[an[q].id] += mid_ans * an[q].ty;
}
rep(q, 1, Q) printf("%lld\n", ans[q]);
return 0;
}

麻烦的解法

对于两个区间\([l,r],[l1,r1](l \leq l1)\),分三类容斥:

  1. 没有交
  2. \([l1,r1]\)被\([l,r]\)包含
  3. 两个区间相交且没有包含关系

对于1

\([l,r]\)值为K数有x,\([r+1,l1-1]\)值为K数有y,\([l1,r1]\)值为K数有z。

\[xz= {(x+y+z)^2-(x+y)^2-(y+z)^2+y^2\over 2}
\]

因此可以拆成4个区间计算。

对于2

\([l,l1-1]\)值为K数有x,\([l1,r1]\)值为K数有y,\([r1+1,r]\)值为K数有z。

\[y(x+y+z)={(x+y)^2+(y+z)^2-x^2-z^2 \over 2}
\]

因此可以拆成4个区间计算。

对于3

\([l,l1-1]\)值为K数有x,\([l1,r]\)值为K数有y,\([r+1,r1]\)值为K数有z。

\[(x+y)(y+z)= {(x+y+z)^2-x^2-z^2+y^2\over 2}
\]

因此可以拆成4个区间计算。

综上

一遍莫队即可,计算区间中相同数个数的平方的和。

#include<bits/stdc++.h>
#define rep(q,a,b) for(int q=a,q##_end_=b;q<=q##_end_;++q)
#define dep(q,a,b) for(int q=a,q##_end_=b;q>=q##_end_;--q)
#define mem(a,b) memset(a,b,sizeof a )
#define debug(a) cerr<<#a<<' '<<a<<"___"<<endl
using namespace std;
bool cur1;
char buf[10000000],*p1=buf,*p2=buf;
#define Getchar() p1==p2&&(p2=(p1=buf)+fread(buf,1,10000000,stdin),p1==p2)?EOF:*p1++
void in(int &r) {
static char c;
r=0;
while(c=Getchar(),c<48);
do r=(r<<1)+(r<<3)+(c^48);
while(c=Getchar(),c>47);
}
const int mn=50005;
int K,n,val[mn];
long long ans[mn];
struct node{
int l,r,id,ty;
bool operator <(const node &A)const{
return l/K==A.l/K?(l/K&1?r>A.r:r<A.r):l/K<A.l/K;
}
}an[mn*4];
int cnt[mn];
long long mid_ans;
bool cur2;
int main(){
// cerr<<(&cur2-&cur1)/1024.0/1024<<endl;
in(n);
K=sqrt(n)+1;
rep(q,1,n)in(val[q]);
int Q;
in(Q);
int l,r,l1,r1;
int ct=0;
rep(q,1,Q){
in(l),in(r),in(l1),in(r1);
if(l>l1)swap(l,l1),swap(r,r1);
if(r<l1){
an[++ct]={l,r1,q,1};
an[++ct]={l,l1-1,q,-1};
an[++ct]={r+1,r1,q,-1};
if(l1-1>=r+1)an[++ct]={r+1,l1-1,q,1};
}else if(r1<=r){
an[++ct]={l,r1,q,1};
an[++ct]={l1,r,q,1};
if(l<=l1-1)an[++ct]={l,l1-1,q,-1};
if(r1+1<=r)an[++ct]={r1+1,r,q,-1};
}else{
an[++ct]={l,r1,q,1};
an[++ct]={l1,r,q,1};
if(l<=l1-1)an[++ct]={l,l1-1,q,-1};
if(r+1<=r1)an[++ct]={r+1,r1,q,-1};
}
}
sort(an+1,an+ct+1);
mid_ans=1,cnt[val[1]]=1;
l=1,r=1;
rep(q,1,ct){
while(l>an[q].l)--l,mid_ans+=(cnt[val[l]]++)<<1|1;
while(r<an[q].r)++r,mid_ans+=(cnt[val[r]]++)<<1|1;
while(l<an[q].l)mid_ans-=(--cnt[val[l]])<<1|1,++l;
while(r>an[q].r)mid_ans-=(--cnt[val[r]])<<1|1,--r;
ans[an[q].id]+=mid_ans*an[q].ty;
}
rep(q,1,Q)printf("%lld\n",ans[q]>>1);
return 0;
}

「SNOI2017」一个简单的询问的更多相关文章

  1. loj #2254. 「SNOI2017」一个简单的询问

    #2254. 「SNOI2017」一个简单的询问 题目描述 给你一个长度为 NNN 的序列 aia_ia​i​​,1≤i≤N1\leq i\leq N1≤i≤N,和 qqq 组询问,每组询问读入 l1 ...

  2. loj2254 「SNOI2017」一个简单的询问

    ref #include <algorithm> #include <iostream> #include <cstdio> #include <cmath& ...

  3. [SNOI2017]一个简单的询问

    [SNOI2017]一个简单的询问 题目大意: 给定一个长度为\(n(n\le50000)\)的序列\(A(1\le A_i\le n)\),定义\(\operatorname{get}(l,r,x) ...

  4. 【BZOJ5016】[Snoi2017]一个简单的询问 莫队

    [BZOJ5016][Snoi2017]一个简单的询问 Description 给你一个长度为N的序列ai,1≤i≤N和q组询问,每组询问读入l1,r1,l2,r2,需输出 get(l,r,x)表示计 ...

  5. loj #2255. 「SNOI2017」炸弹

    #2255. 「SNOI2017」炸弹 题目描述 在一条直线上有 NNN 个炸弹,每个炸弹的坐标是 XiX_iX​i​​,爆炸半径是 RiR_iR​i​​,当一个炸弹爆炸时,如果另一个炸弹所在位置 X ...

  6. loj#2255. 「SNOI2017」炸弹 线段树优化建图,拓扑,缩点

    loj#2255. 「SNOI2017」炸弹 线段树优化建图,拓扑,缩点 链接 loj 思路 用交错关系建出图来,发现可以直接缩点,拓扑统计. 完了吗,不,瓶颈在于边数太多了,线段树优化建图. 细节 ...

  7. bzoj P5016[Snoi2017]一个简单的询问——solution

    Description 给你一个长度为N的序列ai,1≤i≤N和q组询问,每组询问读入l1,r1,l2,r2,需输出   get(l,r,x)表示计算区间[l,r]中,数字x出现了多少次. Input ...

  8. LOJ——#2256. 「SNOI2017」英雄联盟

    https://loj.ac/problem/2256 题目描述 正在上大学的小皮球热爱英雄联盟这款游戏,而且打的很菜,被网友们戏称为「小学生」.现在,小皮球终于受不了网友们的嘲讽,决定变强了,他变强 ...

  9. bzoj 5016: [Snoi2017]一个简单的询问

    Description 给你一个长度为N的序列ai,1≤i≤N和q组询问,每组询问读入l1,r1,l2,r2,需输出 get(l,r,x)表示计算区间[l,r]中,数字x出现了多少次. Input 第 ...

随机推荐

  1. localstorage的浏览器支持情况

    localStorage的兼容性不错,就国内的情况,已经基本没有问题了.localStorage的原理很简单,浏览器为每个域名划出一块本地存储空间,用户网页可以通过localStorage命名空间进行 ...

  2. Python_time&datetime

    获取常用日常时间 # encoding: utf-8 import time import datetime # 当前时间 datetime_now_time = datetime.datetime. ...

  3. django 使用createView创建视图是form_valid()没有通过?

    django 使用createView创建视图是form_valid()没有通过的原因: fields中定义的字段要与from表单中的字段相对应 修改后 接着又报错: 查看没有取到id,最后通过req ...

  4. 阿里云服务器ECS Ubuntu16.04 + Seafile 搭建私人网盘 (Seafile Pro)

    原文链接:? 传送门 本文主要讲述 使用 Ubuntu 16.04 云服务器 通过脚本实现对 Seafile Pro 的安装,完成私人网盘的搭建 首先给出 Seafile 专业版的下载地址(Linux ...

  5. Git 的基本命令的使用

    1.获得Git仓库(克隆一份代码到本地仓库) git clone url 2.更新本地的代码 git pull 3.查看本地修改的文件 git status 4.将本地的修改加到stage中 git ...

  6. Spring循环依赖原理

    Spring循环依赖的原理解析 1.什么是循环依赖? ​ 我们使用Spring的时候,在一个对象中注入另一个对象,但是另外的一个对象中也包含该对象.如图: 在Student中包含了teacher的一个 ...

  7. JUC之读写锁问题

    读写锁 读写锁在同一时刻可以允许多个读线程访问,但是在写线程访问时,所有的读线程和其他写线程均被阻塞.读写锁维护了一对锁,一个读锁和一个写锁,通过分离读锁和写锁,使得并发性相比一般的排他锁有了很大提升 ...

  8. CTF-sql-sql约束注入

    create table user( id int not null auto_increment, username varchar(30) not null, password varchar(3 ...

  9. 封装OCX

    封装OCX的办法有2种: 1. 使用C++的MFC activex项目生成OCX 2. 使用C#的用户控件生成OCX(.net core好像不支持) 注意:以管理员身份运行Visual Studio ...

  10. 《剑指offer》面试题63. 股票的最大利润

    问题描述 假设把某股票的价格按照时间先后顺序存储在数组中,请问买卖该股票一次可能获得的最大利润是多少? 示例 1: 输入: [7,1,5,3,6,4] 输出: 5 解释: 在第 2 天(股票价格 = ...