写了一小时结果被卡常了(笑。

考虑新加入一个数什么时候会产生贡献,或者什么时候不会产生贡献。

发现当一个数的位置与他前一次出现时的位置所构成的区间内假若有一个比它小的数那么就不得不对这个数新进行一次操作而不能共用。

又因为询问一个值域范围内的贡献,所以考虑把这个范围内最大的小于这个数本身的数找出来就行了。

我们令这个数作为这个点的点权。

询问便是询问一个值域范围内的点有多少个点权也满足在这个值域范围内,考虑按照大小重新给所有点定序,值域限制转变为下标限制,这个问题就变成了一个二维数点。差分之后树状数组扫一遍就行了。

考虑怎么预处理一个点的点权,我们可以将所有点从小到大加入线段树并维护区间最大值即可。

复杂度 \(O(n \log n)\)。

下面放出赛后卡过的代码:

#include<bits/stdc++.h>
#pragma GCC optimize("Ofast")
#define lowbit(x) (x&-(x))
using namespace std;
namespace IO{
const int SIZE=1<<21;
static char ibuf[SIZE],obuf[SIZE],*iS,*iT,*oS=obuf,*oT=oS+SIZE-1;
int qr;
char qu[55],c;
bool f;
#define getchar() (IO::iS==IO::iT?(IO::iT=(IO::iS=IO::ibuf)+fread(IO::ibuf,1,IO::SIZE,stdin),(IO::iS==IO::iT?EOF:*IO::iS++)):*IO::iS++)
#define putchar(x) *IO::oS++=x,IO::oS==IO::oT?flush():0
#define flush() fwrite(IO::obuf,1,IO::oS-IO::obuf,stdout),IO::oS=IO::obuf
#define puts(x) IO::Puts(x)
template<typename T>
inline void read(T&x){
for(f=1,c=getchar();c<48||c>57;c=getchar())f^=c=='-';
for(x=0;c<=57&&c>=48;c=getchar()) x=(x<<1)+(x<<3)+(c&15);
x=f?x:-x;
}
template<typename T>
inline void write(T x){
if(!x) putchar(48); if(x<0) putchar('-'),x=-x;
while(x) qu[++qr]=x%10^48,x/=10;
while(qr) putchar(qu[qr--]);
}
inline void Puts(const char*s){
for(int i=0;s[i];i++)
putchar(s[i]);
putchar('\n');
}
struct Flusher_{~Flusher_(){flush();}}io_flusher_;
}
using IO::read;
using IO::write;
const int maxn = 1e6+14;
const int inf = 1e9+7;
int tr[maxn*3+1],tag[maxn*3+1];
inline void pushdown(int cur){
if(tr[cur]==inf) return ;
tr[cur<<1]=min(tr[cur<<1],tag[cur]);
tr[cur<<1|1]=min(tr[cur<<1|1],tag[cur]);
tag[cur<<1]=min(tag[cur<<1],tag[cur]);
tag[cur<<1|1]=min(tag[cur<<1|1],tag[cur]);
tag[cur]=inf;
}
inline void pushup(int cur){
tr[cur]=min(tr[cur<<1],tr[cur<<1|1]);
}
inline void update(int cur,int lt,int rt,int l,int r,int v){
if(lt>rt) return ;
if(l>rt||r<lt) return;
if(l<=lt&&rt<=r){
tr[cur]=min(tr[cur],v);
tag[cur]=min(tag[cur],v);
return ;
}
int mid=(lt+rt)>>1;
pushdown(cur);
update(cur<<1,lt,mid,l,r,v);
update(cur<<1|1,mid+1,rt,l,r,v);
pushup(cur);
}
inline int query(int cur,int lt,int rt,int l,int r){
if(l>rt||r<lt) return inf;
if(l<=lt&&rt<=r) return tr[cur];
int mid=(lt+rt)>>1;
pushdown(cur);
return min(query(cur<<1,lt,mid,l,r),query(cur<<1|1,mid+1,rt,l,r));
}
int Tr[maxn*3+1],Tag[maxn*3+1];
inline void Pushdown(int cur){
if(Tag[cur]==0) return ;
Tr[cur<<1]=max(Tr[cur<<1],Tag[cur]);
Tr[cur<<1|1]=max(Tr[cur<<1|1],Tag[cur]);
Tag[cur<<1]=max(Tag[cur<<1],Tag[cur]);
Tag[cur<<1|1]=max(Tag[cur<<1|1],Tag[cur]);
Tag[cur]=0;
}
inline void Pushup(int cur){
Tr[cur]=max(Tr[cur<<1],Tr[cur<<1|1]);
}
inline void Update(int cur,int lt,int rt,int l,int r,int v){
if(lt>rt) return ;
if(l>rt||r<lt) return;
if(l<=lt&&rt<=r){
Tr[cur]=max(Tr[cur],v);
Tag[cur]=max(Tag[cur],v);
return ;
}
int mid=(lt+rt)>>1;
Pushdown(cur);
Update(cur<<1,lt,mid,l,r,v);
Update(cur<<1|1,mid+1,rt,l,r,v);
Pushup(cur);
}
inline int Query(int cur,int lt,int rt,int l,int r){
if(l>rt||r<lt) return 0;
if(l<=lt&&rt<=r) return Tr[cur];
int mid=(lt+rt)>>1;
Pushdown(cur);
return max(Query(cur<<1,lt,mid,l,r),Query(cur<<1|1,mid+1,rt,l,r));
}
int w[maxn],a[maxn],n,q;
int lst[maxn];
int b[maxn];
int L[maxn],R[maxn];
vector<int> col[maxn];
int cnt;
int answer[maxn];
struct Node{
Node(int L,int R,int ID,int OP){
l=L,r=R,id=ID,op=OP;
}
int l,r,id,op;
};
int tree[maxn];
inline void add(int x){
while(x<=n) tree[x]++,x+=lowbit(x);
}
inline int pre(int x){
int res=0;
while(x>0) res+=tree[x],x-=lowbit(x);
return res;
}
vector<Node> Q[maxn];
int f[maxn];
int main(){
read(n);
read(q);
for(int i=1;i<=n;i++){
read(a[i]);
}
for(int i=1;i<=n;i++){
col[a[i]].push_back(i);
if(lst[a[i]]==0){
w[i]=0;
}
else{
w[i]=-1;
}
lst[a[i]]=i;
}
for(int i=1;i<=n;i++){
int lst=0;
for(int x:col[i]){
if(lst==0) w[x]=0;
else{
w[x]=Query(1,1,n,lst,x);
if(w[x]==0) w[x]=-1;
}
lst=x; }
for(int x:col[i]) Update(1,1,n,x,x,a[x]);
}
for(int i=1;i<=n;i++){
if(col[i].size()==0){
L[i]=n+1;
R[i]=0;
continue;
}
L[i]=cnt+1;
for(int x:col[i]) b[++cnt]=w[x],f[cnt]=x;
R[i]=cnt;
}
for(int i=0;i<(maxn*3);i++) tr[i]=tag[i]=inf;
for(int i=0;i<(maxn*3);i++) Tr[i]=Tag[i]=0;
for(int i=1;i<=n;i++){
update(1,1,n,i,i,L[i]);
Update(1,1,n,i,i,R[i]);
}
for(int i=1;i<=q;i++){
int cl,cr;
read(cl);
read(cr);
int L=query(1,1,n,cl,cr),R=Query(1,1,n,cl,cr);
if(L>R) continue;
Q[L-1].push_back(Node(cl,cr,i,-1));
Q[R].push_back(Node(cl,cr,i,1));
}
int sum=0;
for(int i=1;i<=n;i++){
if(w[f[i]]==0) sum++;
else if(w[f[i]]==-1) sum=sum;
else add(w[f[i]]);
for(Node now:Q[i]){
answer[now.id]+=now.op*(sum+(pre(now.r)-pre(now.l-1)));
}
}
for(int i=1;i<=q;i++) write(answer[i]),putchar('\n');
return 0;
}
/*
10 1
1 6 2 3 2 6 3 10 1 2
3 6
*/

CF1864F 题解的更多相关文章

  1. 2016 华南师大ACM校赛 SCNUCPC 非官方题解

    我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...

  2. noip2016十连测题解

    以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...

  3. BZOJ-2561-最小生成树 题解(最小割)

    2561: 最小生成树(题解) Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1628  Solved: 786 传送门:http://www.lyd ...

  4. Codeforces Round #353 (Div. 2) ABCDE 题解 python

    Problems     # Name     A Infinite Sequence standard input/output 1 s, 256 MB    x3509 B Restoring P ...

  5. 哈尔滨理工大学ACM全国邀请赛(网络同步赛)题解

    题目链接 提交连接:http://acm-software.hrbust.edu.cn/problemset.php?page=5 1470-1482 只做出来四道比较水的题目,还需要加强中等题的训练 ...

  6. 2016ACM青岛区域赛题解

    A.Relic Discovery_hdu5982 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Jav ...

  7. poj1399 hoj1037 Direct Visibility 题解 (宽搜)

    http://poj.org/problem?id=1399 http://acm.hit.edu.cn/hoj/problem/view?id=1037 题意: 在一个最多200*200的minec ...

  8. 网络流n题 题解

    学会了网络流,就经常闲的没事儿刷网络流--于是乎来一发题解. 1. COGS2093 花园的守护之神 题意:给定一个带权无向图,问至少删除多少条边才能使得s-t最短路的长度变长. 用Dijkstra或 ...

  9. CF100965C题解..

    求方程 \[ \begin{array}\\ \sum_{i=1}^n x_i & \equiv & a_1 \pmod{p} \\ \sum_{i=1}^n x_i^2 & ...

  10. JSOI2016R3 瞎BB题解

    题意请看absi大爷的blog http://absi2011.is-programmer.com/posts/200920.html http://absi2011.is-programmer.co ...

随机推荐

  1. gorm使用小结

    增 db.Create(user) db.Save(user) 参数只能用**结构体指针****,因为要根据指针写入该条插入的数据, 所以user可以作为该条数据使用. 新增只能用结构体 save方法 ...

  2. NASM中的内存引用

    NASM对于内存的引用规则非常简单,如果想访问内存中的内容,就将地址用[]包围,如果没有[],就表示是地址本身,而不是内容. mov ax,[wordvar] mov ax,[wordvar+1] m ...

  3. 小程序中 canvas 的图片不支持 base64 格式

    首先使用 wx.base64ToArrayBuffer 将 base64 数据转换为 ArrayBuffer 数据,使用FileSystemManager.writeFile 将 ArrayBuffe ...

  4. linux下vim的使用以及高效率的技巧

    目录 一.关于vim编辑器 二.vim编辑器的模式 三.一般模式下的基础操作 四.V模式(列模式)的基础操作 五.命令模式下的基础操作 六.自定义vim环境 七.vim同时打开多个文件 八.比较两个文 ...

  5. StackExchange.Redis跑起来,为什么这么溜?

    StackExchange.Redis 是一个高性能的 Redis 客户端库,主要用于 .NET 环境下与 Redis 服务器进行通信,大名鼎鼎的stackoverflow 网站就使用它.它使用异步编 ...

  6. python利用flux基本读写influxDB

    1.读取 QuerApi 形式 python 利用 flux 语句查询 influxdb 数据. https://influxdb-client.readthedocs.io/en/latest/ap ...

  7. 剑指Offer-67.剪绳子(C++/Java)

    题目: 给你一根长度为n的绳子,请把绳子剪成整数长的m段(m.n都是整数,n>1并且m>1),每段绳子的长度记为k[0],k[1],...,k[m].请问k[0]xk[1]x...xk[m ...

  8. linux系统下,安装redis教程,以redis 6.2.6为例

    1.下载安装包 手动下载:进入官网选择下载版本https://download.redis.io/releases/ 命令下载: cd /usr/local wget http://download. ...

  9. ABC319题解

    直接从 D 开始了. D 可可爱爱的二分捏. check 就按照题目里写的就行了. 然后 \(l\) 的初值要注意一下,就是 \(\max^{i \le n}_{i=1}a_i\). 代码: #inc ...

  10. The remote name could not be resolved

    HTTP The remote name could not be resolved HTTP Status:NameResolutionFailure