题目大意:n个数字,m次操作,支持修改一个数字和查询一个区间内每种数字最大出现位置减最小出现位置的和。(n,m<=100,000)

做法:把每个数字表示成二维平面上的点,第一维是在数组中的位置,第二维是在数组中前一个相同数字的位置,权值为这两个位置的差,询问等同于求矩形和,修改时会影响自己和相邻的相同数字,每种开一个set维护即可。矩形和可以用cdq分治,不容易被卡空间。

代码:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<vector>
#include<cstdio>
#include<queue>
#include<map>
#include<set>
using namespace std;
inline int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
#define MN 100000
#define N 131072
set<int> s[MN+];
int a[MN+],ls[MN+],wn,qn,pn;
long long ans[MN+],t[N*+];
struct work{int t,a,b,c;}w[MN*+];
struct P{int t,a,b,c,d;}p[MN*+];
bool cmp(const P&a,const P&b){return a.a==b.a?a.t<b.t:a.a<b.a;}
void add(int k,int x){for(k+=N;k;k>>=)t[k]+=x;}
long long query(int l,int r)
{
long long res=;
for(l+=N-,r+=N+;l^r^;l>>=,r>>=)
{
if(~l&)res+=t[l+];
if( r&)res+=t[r-];
}
return res;
}
void solve(int l,int r)
{
int mid=l+r>>,i;
if(l<r)solve(l,mid),solve(mid+,r);
for(pn=,i=l;i<=mid;++i)if(w[i].t<)p[++pn]=(P){,w[i].a,w[i].b,w[i].c,};
for(;i<=r;++i)if(w[i].t>)p[++pn]=(P){,w[i].a-,w[i].a,w[i].b,w[i].c},
p[++pn]=(P){,w[i].b,w[i].a,w[i].b,w[i].c};
sort(p+,p+pn+,cmp);
for(i=;i<=pn;++i)
{
if(p[i].t==)add(p[i].b,p[i].c);
if(p[i].t==)ans[p[i].d]-=query(p[i].b,p[i].c);
if(p[i].t==)ans[p[i].d]+=query(p[i].b,p[i].c);
}
for(i=;i<=pn;++i)if(p[i].t==)add(p[i].b,-p[i].c);
}
int main()
{
int n,m,i,t,x,y;
n=read();m=read();
for(i=;i<=n;s[a[i]].insert(ls[a[i]]=i),++i)
if(ls[a[i]=read()])w[++wn]=(work){,i,ls[a[i]],i-ls[a[i]]};
for(i=;i<=m;++i)
{
t=read();x=read();y=read();
if(t==)
{
set<int>::iterator i=s[a[x]].find(x),j=i,k=i;++k;
if(i!=s[a[x]].begin())
{
--j;w[++wn]=(work){,x,*j,*j-x};
if(k!=s[a[x]].end())w[++wn]=(work){,*k,*j,*k-*j};
}
if(k!=s[a[x]].end())w[++wn]=(work){,*k,x,x-*k};
s[a[x]].erase(i);
s[a[x]=y].insert(x);
i=j=k=s[y].find(x);++k;
if(i!=s[y].begin())
{
--j;w[++wn]=(work){,x,*j,x-*j};
if(k!=s[y].end())w[++wn]=(work){,*k,*j,*j-*k};
}
if(k!=s[y].end())w[++wn]=(work){,*k,x,*k-x};
}
else w[++wn]=(work){,x,y,++qn};
}
solve(,wn);
for(i=;i<=qn;++i)printf("%I64d\n",ans[i]);
}

[Codeforces]848C - Goodbye Souvenir的更多相关文章

  1. Codeforces 848C Goodbye Souvenir(CDQ 分治)

    题面传送门 考虑记录每个点的前驱 \(pre_x\),显然答案为 \(\sum\limits_{i=l}^{r} i-pre_i (pre_i \geq l)\) 我们建立一个平面直角坐标系,\(x\ ...

  2. Codeforces 848C Goodbye Souvenir [CDQ分治,二维数点]

    洛谷 Codeforces 这题我写了四种做法-- 思路 不管做法怎样,思路都是一样的. 好吧,其实不一样,有细微的差别. 第一种 考虑位置\(x\)对区间\([l,r]\)有\(\pm x\)的贡献 ...

  3. [Codeforces]849E Goodbye Souvenir

    又是一道比较新的模板题吧,即使是在Codeforces上小C还是贴了出来. Description 给定一个长度为n的序列a1~an,每个元素代表一种颜色.m次操作,每次操作为两种中的一种: 1 p ...

  4. Codeforces 848C (cdq分治)

    Codeforces 848C Goodbye Souvenir Problem : 给一个长度为n的序列,有q个询问.一种询问是修改某个位置的数,另一种询问是询问一段区间,对于每一种值出现的最右端点 ...

  5. 【Codeforces 848C】Goodbye Souvenir

    Codeforces 848 C 题意:给\(n\)个数,\(m\)个询问,每一个询问有以下类型: 1 p x:将第p位改成x. 2 l r:求出\([l,r]\)区间中每一个出现的数的最后一次出现位 ...

  6. CF848C:Goodbye Souvenir(CDQ分治)

    Description 给定长度为$n$的数组, 定义数字$X$在$[l,r]$内的值为数字$X$在$[l,r]$内最后一次出现位置的下标减去第一次出现位置的下标给定$m$次询问, 每次询问有三个整数 ...

  7. codeforces 848c - two TVs

    2017-08-22 15:42:44 writer:pprp 参考:http://blog.csdn.net/qq_37497322/article/details/77463376#comment ...

  8. 【Codeforces Round 431 (Div. 2) A B C D E五个题】

    先给出比赛地址啦,感觉这场比赛思维考察非常灵活而美妙. A. Odds and Ends ·述大意:      输入n(n<=100)表示长度为n的序列,接下来输入这个序列.询问是否可以将序列划 ...

  9. Codeforces Goodbye 2018

    Goodbye 2018 可能是我太菜考试的时候出不了$E$ 可能是我太菜考试的时候调不出$F$ 所以转化为手速场之后手速还上不去.jpg A 模拟题意... #include <cstdio& ...

随机推荐

  1. 201621123062《Java程序设计》第一周学习总结

    1.本周学习总结 关键词: 初步熟悉Java的基本组成.语言特点(简单性.结构中立性).运行环境.简单语法等. 关键概念之间的联系: 1.JVM是Java程序唯一认识的操作系统,其可执行文件为.cla ...

  2. prototype 原型链

    // 方法1 var aa=function(){ function bb(){ this.name="1111"; console.log(this.name) }; bb.pr ...

  3. python 面向对象之继承与派生

    一:初识继承 1,什么是继承? 继承指的是类与类之间的关系,是一种什么"是"什么的关系,继承的功能之一就是用来解决代码重用问题 继承是一种创建新类的方式,在python中,新建的类 ...

  4. 我的PCB电路设计(一)

    我的制板规则 过孔大小:14/24mil-(12/22-28/50)  一般过孔没必要太大.如果电流较大可以适当增大过孔,或者多加几个过孔 线宽大小:小信号线8mil,大电流线不等按1A电流30mil ...

  5. Oracle闪回技术

    (一)闪回技术概要 闪回技术是数据库备份与恢复的重要补充手段,主要包括以下7种特性: 特性 原理 数据库支持 闪回查询(Flashback Query) 利用undo表空间中的回退信息,查询过去某个时 ...

  6. Windows用户模式下注入方式总结

    注入技术在病毒木马.游戏.打补丁等编程中应用很广泛,学习该技术不仅能帮助理解Windows工作原理,还能对病毒木马技术手段有更加深刻的理解,下面我们了解下各种注入方式吧. 一.DLL注入 在注入技术中 ...

  7. 阿里云API网关(9)常见问题

    网关指南: https://help.aliyun.com/document_detail/29487.html?spm=5176.doc48835.6.550.23Oqbl 网关控制台: https ...

  8. Python3安装Requests

    安装Requests费了1天的时间,囧.终于还是在官网找到解决方法,可以参考这个http://docs.python-requests.org/en/latest/user/install/#inst ...

  9. 32位centos6.5 mysql rpm包下载

    查看centos版本号和位数: http://www.cnblogs.com/grey-wolf/p/7472507.html mysql下载: 1.进入https://dev.mysql.com/d ...

  10. 如何从0开发一个Atom组件

    最近用Atom写博客比较多,然后发现一个很严重的问题..没有一个我想要的上传图片的方式,比如某乎上边就可以直接copy/paste文件,然后进行上传.然而在Atom上没有找到类似的插件,最接近的一个, ...