codeforces 652C C. Foe Pairs(尺取法+线段树查询一个区间覆盖线段)
题目链接:
1 second
256 megabytes
standard input
standard output
You are given a permutation p of length n. Also you are given m foe pairs (ai, bi) (1 ≤ ai, bi ≤ n, ai ≠ bi).
Your task is to count the number of different intervals (x, y) (1 ≤ x ≤ y ≤ n) that do not contain any foe pairs. So you shouldn't count intervals (x, y) that contain at least one foe pair in it (the positions and order of the values from the foe pair are not important).
Consider some example: p = [1, 3, 2, 4] and foe pairs are {(3, 2), (4, 2)}. The interval (1, 3) is incorrect because it contains a foe pair(3, 2). The interval (1, 4) is also incorrect because it contains two foe pairs (3, 2) and (4, 2). But the interval (1, 2) is correct because it doesn't contain any foe pair.
The first line contains two integers n and m (1 ≤ n, m ≤ 3·10^5) — the length of the permutation p and the number of foe pairs.
The second line contains n distinct integers pi (1 ≤ pi ≤ n) — the elements of the permutation p.
Each of the next m lines contains two integers (ai, bi) (1 ≤ ai, bi ≤ n, ai ≠ bi) — the i-th foe pair. Note a foe pair can appear multiple times in the given list.
Print the only integer c — the number of different intervals (x, y) that does not contain any foe pairs.
Note that the answer can be too large, so you should use 64-bit integer type to store it. In C++ you can use the long long integer type and in Java you can use long integer type.
4 2
1 3 2 4
3 2
2 4
5
9 5
9 7 2 3 1 4 6 5 8
1 6
4 5
2 7
7 2
2 7
20
In the first example the intervals from the answer are (1, 1), (1, 2), (2, 2), (3, 3) and (4, 4).
题意:
给一个数组,问有多少对(i,j)满足[a[i],a[j]]中不完整包含任何一个数对;
思路:
暴力是的复杂度太高,我先把这些数对都处理成原数组的位置,然后把它们搞进线段树里,就是把右端点当成左端点插入线段树时的位置,查询一个区间[i,j]时是否包含一个完整的线段可以看[i,j]中最大的左端点是多大,如果最大的左端点>=i时,我们就知道[i,j]中至少包含一个完整的线段;然后再枚举左端点,尺取法找右端点;然后把长度都加起来就是结果啦;
AC代码:
/*2014300227 652C - 11 GNU C++11 Accepted 311 ms 18796 KB*/
#include <bits/stdc++.h>
using namespace std;
const int N=3e5+;
typedef long long ll;
int n,a[N],fa[N],m,l,r;
struct Tree
{
int l,r,ans;
};
Tree tree[*N];
void Pushup(int node)
{
tree[node].ans=max(tree[*node].ans,tree[*node+].ans);
}
void build(int node,int L,int R)
{
tree[node].l=L;
tree[node].r=R;
if(L==R)
{
tree[node].ans=;
return ;
}
int mid=(L+R)>>;
build(*node,L,mid);
build(*node+,mid+,R);
Pushup(node);
}
void update(int node,int num,int pos)
{
if(tree[node].l==tree[node].r&&tree[node].r==pos)
{
tree[node].ans=max(tree[node].ans,num);
return ;
}
int mid=(tree[node].l+tree[node].r)>>;
if(pos<=mid)update(*node,num,pos);
else update(*node+,num,pos);
Pushup(node);
}
int query(int node,int L,int R)
{
if(L<=tree[node].l&&R>=tree[node].r)
{
return tree[node].ans;
}
int mid=(tree[node].l+tree[node].r)>>;
if(R<=mid)return query(*node,L,R);
else if(L>mid)return query(*node+,L,R);
else return max(query(*node,L,mid),query(*node+,mid+,R));
}
struct PO
{
int l,r;
}po[N];
int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)
{
scanf("%d",&a[i]);
fa[a[i]]=i;
}
build(,,n);
for(int i=;i<m;i++)
{
scanf("%d%d",&l,&r);
po[i].l=min(fa[l],fa[r]);
po[i].r=max(fa[l],fa[r]);
update(,po[i].l,po[i].r);//更新;
}
ll ans=;
int l=,r=;
for(int i=;i<=n;i++)
{
l=i;
while(r<=n)
{
int q=query(,i,r);//查询[i,r]中的最大值,即是包含于这个区间的线段最大的左端点;
if(q<i)r++;//r为以l为左端点满足要求的最长的区间的右端点+1;
else break;
}
ans+=(ll)(r-l);
}
cout<<ans<<"\n";
return ;
}
codeforces 652C C. Foe Pairs(尺取法+线段树查询一个区间覆盖线段)的更多相关文章
- 数据结构1 线段树查询一个区间的O(log N) 复杂度的证明
线段树属于二叉树, 其核心特征就是支持区间加法,这样就可以把任意待查询的区间$[L, R]$分解到线段树的节点上去,再把这些节点的信息合并起来从而得到区间$[L,R]$的信息. 下面证明在线段树上查询 ...
- 数据结构1 「在线段树中查询一个区间的复杂度为 $O(\log N)$」的证明
线段树属于二叉树, 其核心特征就是支持区间加法,这样就可以把任意待查询的区间$[L, R]$分解到线段树的节点上去,再把这些节点的信息合并起来从而得到区间$[L,R]$的信息. 下面证明在线段树上查询 ...
- codeforces Good bye 2016 E 线段树维护dp区间合并
codeforces Good bye 2016 E 线段树维护dp区间合并 题目大意:给你一个字符串,范围为‘0’~'9',定义一个ugly的串,即串中的子串不能有2016,但是一定要有2017,问 ...
- HDU 1754 I Hate It(线段树单点替换+区间最值)
I Hate It [题目链接]I Hate It [题目类型]线段树单点替换+区间最值 &题意: 本题目包含多组测试,请处理到文件结束. 在每个测试的第一行,有两个正整数 N 和 M ( 0 ...
- HDU 3577Fast Arrangement(线段树模板之区间增减更新 区间求和查询)
Fast Arrangement Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) ...
- POJ 3468 A Simple Problem with Integers(线段树模板之区间增减更新 区间求和查询)
A Simple Problem with Integers Time Limit: 5000MS Memory Limit: 131072K Total Submissions: 140120 ...
- POJ.3321 Apple Tree ( DFS序 线段树 单点更新 区间求和)
POJ.3321 Apple Tree ( DFS序 线段树 单点更新 区间求和) 题意分析 卡卡屋前有一株苹果树,每年秋天,树上长了许多苹果.卡卡很喜欢苹果.树上有N个节点,卡卡给他们编号1到N,根 ...
- POJ.2299 Ultra-QuickSort (线段树 单点更新 区间求和 逆序对 离散化)
POJ.2299 Ultra-QuickSort (线段树 单点更新 区间求和 逆序对 离散化) 题意分析 前置技能 线段树求逆序对 离散化 线段树求逆序对已经说过了,具体方法请看这里 离散化 有些数 ...
- HDU.1394 Minimum Inversion Number (线段树 单点更新 区间求和 逆序对)
HDU.1394 Minimum Inversion Number (线段树 单点更新 区间求和 逆序对) 题意分析 给出n个数的序列,a1,a2,a3--an,ai∈[0,n-1],求环序列中逆序对 ...
随机推荐
- 【redis】4.spring boot集成redis,实现数据缓存
参考地址:https://spring.io/guides/gs/messaging-redis/ ================================================== ...
- 在DevExpress GridControl中添加进度条控件 z
首先可以使用 DevExpress GridControl 自带的进度条控件. 但是我要用一个方法来设置所有的单元格进度,而不是每个单元格都要设置一遍,同时我想要根据进度值不同,进度条显示不同的颜色. ...
- xpath的匹配规则
starts-with 匹配一个属性开始位置的关键字 contains 匹配一个属性值中包含的字符串 text() 匹配的是显示文本信息,此处也可以用来做定位用 i.e. //input[starts ...
- assign-cookies
https://leetcode.com/problems/assign-cookies/ 用贪心算法即可. package com.company; import java.util.Arrays; ...
- 表现层 JSP 页面实现
一.实验介绍 1.1 实验内容 本节课程主要利用 easyUI 实现系统的前端页面. 1.2 实验知识点 easyUI JavaScript html 1.3 实验环境 JDK1.8 Eclipse ...
- MySQL主从复制技术与读写分离技术amoeba应用
MySQL主从复制技术与读写分离技术amoeba应用 前言:眼下在搭建一个人才站点,估计流量会非常大,须要用到分布式数据库技术,MySQL的主从复制+读写分离技术.读写分离技术有官方的MySQL-pr ...
- 首先使用flex制作table
HTML(JavaScript) <!DOCTYPE html> <html lang="en"> <head> <meta charse ...
- Codeforces Round #313 (Div. 2) ABC
A http://codeforces.com/contest/560/problem/A 推断给出的数能否组成全部自然数. 水题 int a[1010]; bool b[1000010]; int ...
- vs2012 MinGW编译ffmpeg 出现libavdevice/avdevice.c(38) : error C2059: 语法错误:“.”
利用vs2012编译ffmpeg出现以下错误: libavdevice/avdevice.c(38) : error C2059: 语法错误:“.” libavdevice/avdevice.c(40 ...
- CentOs中mysql的安装与配置(转)
在linux中安装数据库首选MySQL,Mysql数据库的第一个版本就是发行在Linux系统上,其他选择还可以有postgreSQL,oracle等 在Linux上安装mysql数据库,我们可以去其官 ...