Educational Codeforces Round 10 C. Foe Pairs

time limit per test1 second
memory limit per test256 megabytes
inputstandard input
outputstandard 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.
Input
The first line contains two integers n and m (1 ≤ n, m ≤ 3·105) — 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.
Output
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.
Examples
Input
Copy
4 2
1 3 2 4
3 2
2 4
Output
Copy
5
Input
Copy
9 5
9 7 2 3 1 4 6 5 8
1 6
4 5
2 7
7 2
2 7
Output
Copy
20
Note
In the first example the intervals from the answer are (1, 1), (1, 2), (2, 2), (3, 3) and (4, 4).

题解:题目的意思是给你一组数,还有几对 敌对数,让你求不包含有 敌对数 的 数组的子区间有几个(包含是全部包含,只有一个不算).

还有一些小细节要注意:给的敌对数可能有重复,位置也可能会变,比如2 7,7 2.

好了,直接直接讲了:这道题,题目给的是什么数不重要,我们只要把数的位置记录下来即可,比如 9 7 2 3 1 4 6 5 8,9的位置是1,敌对 数 1 6 ,1的位置是5,6的位置是7,

那为什么这样可以呢,比如数组子区间[1,5],敌对数在不在里面我们只要看他俩的位置在不在里面即可,类似于区间的包含.

这里我们需要一个数组bin[],来存储敌对数区间的终点,把敌对数转换成区间,如上例,1 6 可换成区间[5,7],那就是 bin[5]=7;还有一个bad数组,存储以该点为终点的敌对数区间有多少个.比如[5,7]敌对数区间,是以7为终点,那么bad[7]就等于1,如果还有其他的敌对数以其为终点再统计.

这题有坑,比如敌对数[1,2],[1,5],那么bin[1]=要设为2,这个讲起来有点麻烦,具体看代码,我就偷懒一下.

然后呢,枚举数列的左端点,再找一下最远可以向右延伸到哪里,就行了,哈哈

#include <bits/stdc++.h>
const int N=3e5+5;
using namespace std;
typedef long long ll;
int m[N];
int bin[N];
int bad[N];
int main()
{
    int n,t,x,y;
    scanf("%d%d",&n,&t);
    int tmp;
    for(int i=1;i<=n;i++){
        scanf("%d",&tmp);
        m[tmp]=i;
        bin[i]=n+1;
    }
    while(t--){
        scanf("%d%d",&x,&y);
        x=m[x],y=m[y];
        if(x>y) swap(x,y);
        bin[x]=min(y,bin[x]);
    }
    ll ans=0;
    //cout<<ans<<endl;
    int j=1;
    for(int i=1;i<=n;i++){
        while(j<=n&&bad[j]==0){
            bad[bin[j]]++;
            j++;
        }
        ans+=j-i;
        //cout<<ans<<endl;
        bad[bin[i]]--;
    }
    printf("%I64d\n",ans);

    //cout << "Hello world!" << endl;
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/-yjun/p/10424401.html
今日推荐