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],求环序列中逆序对 ...
随机推荐
- 邁向IT專家成功之路的三十則鐵律 鐵律十九:IT人待業之道-寬心
說來很多人可能不相信,筆者從來不把失業當作是一件嚴重的事,相反的我會把它當作是一個很好的轉機.針對一個隨時做好準備的IT人,三個月或半年沒有上班完全沒有甚麼好擔心的.只是如何善用待業的時間,說實在的真 ...
- 【mac IntelliJ Idea】mac上 idea快速重写父类方法 快捷键
windows上快捷键: Ctrl+O Mac上快捷键: command+O 在要重写父类方法的位置 ,按下快捷键,然后选择要重写的方法即可.
- alibaba fastjson常见问题FAQ
English | 中文 1. 怎么获得fastjson? 你可以通过如下地方下载fastjson: maven中央仓库: http://central.maven.org/maven2/com/al ...
- 转: How to Install MongoDB 3.2 on CentOS/RHEL & Fedora (简单易懂)
from: http://tecadmin.net/install-mongodb-on-centos-rhel-and-fedora/ MongoDB (named from “huMONGOus ...
- Pearson product-moment correlation coefficient in java(java的简单相关系数算法)
一.什么是Pearson product-moment correlation coefficient(简单相关系数)? 相关表和相关图可反映两个变量之间的相互关系及其相关方向,但无法确切地表明两个变 ...
- css3 - target
通过CSS3伪元素target,我们可以实现拉风琴 源码 <!DOCTYPE HTML> <html lang="en-US"> <head> ...
- C# 将cookie写入WebBrowser
string cookie = ""; foreach (string c in cookie.Split(';')) { string[] item = c.Split('=') ...
- java模拟而一个电话本操作
哈哈.大家平时都在使用电话本.以下使用java来模拟而一个简单的电话本吧... 首先给出联系人的抽象类 package net.itaem.po; /** * * 电话人的信息 * */ public ...
- CUGBACM_Summer_Tranning1 二进制枚举+模拟+离散化
整体感觉:这个组队赛收获还挺多的.自从期末考试以后已经有一个多月没有 做过组队赛了吧,可是这暑假第一次组队赛就找回了曾经的感觉.还挺不错的!继续努力!! 改进的地方:这次组队赛開始的时候题目比較难读懂 ...
- Java RESTful 框架
[转载] 最好的8个 Java RESTful 框架 - 2015 Top 8 Java RESTful Micro Frameworks – Pros/Cons - 2017 Restlet - f ...