牛客网 暑期ACM多校训练营(第一场)J.Different Integers-区间两侧不同数字的个数-离线树状数组 or 可持久化线段树(主席树)
题意就是给你l,r,问你在区间两侧的[1,l]和[r,n]中,不同数的个数。
两种思路:
1.将数组长度扩大两倍,for(int i=n+1;i<=2*n;i++) a[i]=a[i-n];就可以将两个分开的区间合并成一个区间[r,l+n],然后就可以通过主席树求解,套模板就可以了。
但是用主席树有风险,容易写超时,超内存,只能通过50%,初始化数组memset少写一个就过了,而且while(scanf("%d%d",&n,&m)==2)要写成这样,我赛后试了一下while(~scanf("%d%d",&n,&m)),过不了,只能过50%,所以主席树正好卡过去。
代码:
//J-主席树刚好卡过
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<queue>
using namespace std;
const int maxn=*1e5+; struct Node
{
int l,r,sum; }p[maxn*];
int la[maxn],a[maxn],root[maxn];
int n,q,cnt; int build(int l,int r)
{
int nc=++cnt;
p[nc].sum=;
p[nc].l=p[nc].r=;
if(l==r){
return nc;
} int m=l+r>>;
p[nc].l=build(l,m);
p[nc].r=build(m+,r);
return nc;
}
int update(int pos,int c,int v,int l,int r)
{
int nc=++cnt;
p[nc]=p[c];
p[nc].sum+=v;
if(l==r){
return nc;
} int m=l+r>>;
if(m>=pos)
p[nc].l=update(pos,p[c].l,v,l,m);
else
p[nc].r=update(pos,p[c].r,v,m+,r);
return nc;
}
int query(int pos,int c,int l,int r)
{
if(l==r) return p[c].sum;
int m=l+r>>;
if(m>=pos)
return p[p[c].r].sum + query(pos,p[c].l,l,m);
else
return query(pos,p[c].r,m+,r);
}
int main()
{
while(scanf("%d%d",&n,&q)==){
memset(la,-,sizeof(la));
cnt=;
for (int i=;i<=n;i++){
scanf("%d",a+i);
}
for(int i=n+;i<=*n;i++)
a[i]=a[i-n];
n=n*;
root[]=build(,n);
for (int i=;i<=n;i++){
int v=a[i];
if(la[v]==-)
root[i]=update(i,root[i-],,,n);
else{
int t=update(la[v],root[i-],-,,n);
root[i]=update(i,t,,,n);
}
la[v]=i;
}
while(q--){
int x,y;
scanf("%d%d",&x,&y);
printf("%d\n",query(y,root[n/+x],,n));
}
}
}
2.叉姐官方题解思路是树状数组,离线按照 r 从小到大处理询问,考虑没出现的数字个数,假设 r = last[x],那么当 l < first[x] 时,x 没出现,用树状数组维护即可。
唉,真的是长的帅又厉害代码写的还优美,代码写的真的是好看,羡慕(✧◡✧)
代码:(叉姐代码)
#include <bits/stdc++.h> struct Query
{
int l, r, id;
}; bool operator < (const Query& u, const Query& v)
{
return u.r < v.r;
} int main()
{
int n, q;
while (scanf("%d%d", &n, &q) == ) {
std::vector<int> a(n), first(n, -), last(n);
int total = ;
for (int i = ; i < n; ++ i) {
scanf("%d", &a[i]);
a[i] --, last[a[i]] = i;
if (first[a[i]] == -) {
total ++, first[a[i]] = i;
}
}
std::vector<Query> queries;
for (int i = , l, r; i < q; ++ i) {
scanf("%d%d", &l, &r);
queries.push_back(Query {l - , r - , i});
}
std::sort(queries.begin(), queries.end());
std::vector<int> count(n), result(q);
for (int i = , k = ; i < n; ++ i) {
while (k < q && queries[k].r == i) {
int& ref = result[queries[k].id] = total;
for (int j = queries[k].l; j < n; j += ~j & j + ) {
ref -= count[j];
}
k ++;
}
if (last[a[i]] == i) {
for (int j = first[a[i]] - ; ~j; j -= ~j & j + ) {
count[j] ++;
}
}
}
for (int i = ; i < q; ++ i) {
printf("%d\n", result[i]);
}
}
}
自己改了一下叉姐代码加了一点注释的代码:
//J-离线树状数组处理
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
using namespace std;
const int maxn=1e5+;
const int inf=0x3f3f3f3f;
const double eps=1e-;
struct node
{
int l,r,id;
bool operator< (const node &a) const{ //结构体内嵌比较函数
return r<a.r;
}
};
int main()
{
int n,q;
while(~scanf("%d%d",&n,&q)){
vector<int>a(n),first(n, -),last(n);
int total=;
for (int i=;i<n;i++){
scanf("%d",&a[i]);
a[i]--,last[a[i]]=i;//记录元素最后出现的位置
if(first[a[i]]==-){//如果元素之前未出现,则记录第一次出现的位置
total++;
first[a[i]]=i;
}
}
vector<node> queries;
for (int i=;i<q;i++) {
int l,r;
scanf("%d%d",&l,&r);
queries.push_back(node {l-,r-,i});//将区间和id存到容器内
}
sort(queries.begin(),queries.end());//区间右边界升序排序(结构体内内嵌了比较函数)
vector<int>count(n),result(q);
for (int i=,k=;i<n;i++){//树状数组维护
while(k<q&&queries[k].r==i){
int &ref=result[queries[k].id]=total;
for(int j=queries[k].l;j<n;j+=~j&j+){//~j&j+1 +的优先级比&高
ref-=count[j];
}
k++;
}
if(last[a[i]]==i){
for(int j=first[a[i]]-;~j;j-=~j&j+){
count[j]++;//统计没有出现过的元素个数
}
}
}
for (int i=;i<q;i++) {
printf("%d\n",result[i]);
}
}
}
讲道理,我是真的菜,难受。
牛客网 暑期ACM多校训练营(第一场)J.Different Integers-区间两侧不同数字的个数-离线树状数组 or 可持久化线段树(主席树)的更多相关文章
- 牛客网暑期ACM多校训练营 第九场
HPrefix Sum study from : https://blog.csdn.net/mitsuha_/article/details/81774727 k较小.分离x和k. 另外的可能:求a ...
- 牛客网暑期ACM多校训练营(第四场):A Ternary String(欧拉降幂)
链接:牛客网暑期ACM多校训练营(第四场):A Ternary String 题意:给出一段数列 s,只包含 0.1.2 三种数.每秒在每个 2 后面会插入一个 1 ,每个 1 后面会插入一个 0,之 ...
- 牛客网暑期ACM多校训练营(第五场):F - take
链接:牛客网暑期ACM多校训练营(第五场):F - take 题意: Kanade有n个盒子,第i个盒子有p [i]概率有一个d [i]大小的钻石. 起初,Kanade有一颗0号钻石.她将从第1到第n ...
- 牛客网 暑期ACM多校训练营(第二场)A.run-动态规划 or 递推?
牛客网暑期ACM多校训练营(第二场) 水博客. A.run 题意就是一个人一秒可以走1步或者跑K步,不能连续跑2秒,他从0开始移动,移动到[L,R]的某一点就可以结束.问一共有多少种移动的方式. 个人 ...
- 牛客网 暑期ACM多校训练营(第一场)A.Monotonic Matrix-矩阵转化为格子路径的非降路径计数,Lindström-Gessel-Viennot引理-组合数学
牛客网暑期ACM多校训练营(第一场) A.Monotonic Matrix 这个题就是给你一个n*m的矩阵,往里面填{0,1,2}这三种数,要求是Ai,j⩽Ai+1,j,Ai,j⩽Ai,j+1 ,问你 ...
- 牛客网暑期ACM多校训练营(第三场)H Diff-prime Pairs (贡献)
牛客网暑期ACM多校训练营(第三场)H Diff-prime Pairs (贡献) 链接:https://ac.nowcoder.com/acm/contest/141/H来源:牛客网 Eddy ha ...
- 2018牛客网暑期ACM多校训练营(第二场)I- car ( 思维)
2018牛客网暑期ACM多校训练营(第二场)I- car 链接:https://ac.nowcoder.com/acm/contest/140/I来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 ...
- 牛客网 暑期ACM多校训练营(第二场)J.farm-STL(vector)+二维树状数组区间更新、单点查询 or 大暴力?
开心.jpg J.farm 先解释一下题意,题意就是一个n*m的矩形区域,每个点代表一个植物,然后不同的植物对应不同的适合的肥料k,如果植物被撒上不适合的肥料就会死掉.然后题目将每个点适合的肥料种类( ...
- 牛客网暑期ACM多校训练营(第七场)Bit Compression
链接:https://www.nowcoder.com/acm/contest/145/C 来源:牛客网 题目描述 A binary string s of length N = 2n is give ...
- 牛客网暑期ACM多校训练营(第一场) - J Different Integers(线段数组or莫队)
链接:https://www.nowcoder.com/acm/contest/139/J来源:牛客网 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 524288K,其他语言1048 ...
随机推荐
- Fiddler - 使用教程
1.断点调试,修改请求表单和响应数据 命令介绍: bpu在请求开始时中断,bpafter在响应到达时中断,bps在特定http状态码时中断,bpv/bpm在特定请求method时中断. bpu m.t ...
- Freemarker 语法详解
Freemarker 在线中文官方参考手册 Freemarker是一款模板引擎,是一种基于模版生成静态文件的通用工具,它是使用纯java编写的,一般用来生成HTML页面. Freemarker 生成静 ...
- Python面试题之一:解密
Python面试题之一: 说明:就是Python工程师面试题 一.字典转换与正则提取值 1:key与Value交换 a = {'a':1,'b':2} print({value:key for key ...
- 【转载】法线贴图Nomal mapping 原理
法线贴图多用在CG动画的渲染以及游戏画面的制作上,将具有高细节的模型通过映射烘焙出法线贴图,贴在低端模型的法线贴图通道上,使之拥有法线贴图的渲染效果,却可以大大降低渲染时需要的面数和计算内容,从而达到 ...
- rownum浅谈(二)
上篇说到rownum和order by及索引列的关系,明白了通过构建一个子查询把查询结果固定住再取数就可以了 .还是取最近10条创建的用户: select * from (select u.* fro ...
- 集训队日常训练20181124 DIV2
急急忙忙要出去比赛就拉了一场有点sb的题目 5202: 网络寻路 时间限制(普通/Java):1000MS/3000MS 内存限制:65536KByte总提交: 15 ...
- mysql安装目录、配置文件存放位置
linux系统下,如何知道mysql使用的配置文件到底是哪个呢?linux自带的mysql的安装目录又是什么呢?数据存放在什么目录下? 1.linux系统自带的mysql,其安装目录及数据目录查看方法 ...
- Pandas根据条件赋值
我们有以下判断条件,我们想要更改B中的数, 而更改的位置是取决于 A 的. 对于A大于4的位置. 更改B在相应位置上的数为0. df.B[df.A>4] = 0
- 软工实践Alpha冲刺(6/10)
队名:起床一起肝活队 组长博客:博客链接 作业博客:班级博客本次作业的链接 组员情况 组员1(队长):白晨曦 过去两天完成了哪些任务 描述: 已经解决登录注册等基本功能的界面. 完成了主界面的基本布局 ...
- 软工实践Alpha冲刺(5/10)
队名:起床一起肝活队 组长博客:博客链接 作业博客:班级博客本次作业的链接 组员情况 组员1(队长):白晨曦 过去两天完成了哪些任务 描述: 已经解决登录注册等基本功能的界面. 完成了主界面的基本布局 ...