CF961E Tufurama【主席树】

CF961E Tufurama

题意翻译

题目描述

有一天Polycarp决定重看他最喜爱的电视剧《Tufurama》。当他搜索“在线全高清免费观看Tufurama第3季第7集”却只得到第7季第3集的结果时,他很惊讶。这让Polycarp感到疑惑——如果有天他决定重看整个系列却无法找到正确的剧集观看,那该怎么办呢?Polycarp现在想统计一下他被迫用不同方案搜索同一剧集的次数。

电视连续剧有n 季(从1 到n 编号),第i 季有ai 集(从1 到ai 编号)。Polycarp认为如果有一对x 和y (x<y),使第x 季第y 集、第y 季第x 集存在,那么其中一个搜索就会包含错误的内容。请帮助Polycarp统计这样的数对的数量吧!

输入输出格式

输入格式

第一行,一个整数n(1n2105) ,表示季数。

第二行,n 个用空格隔开的整数a1,a2,...,an(1ai109) ,表示每一季的集数

输出格式

只有一行,一个整数,表示x 和y (x<y ),使第x 季第y 集、第y 季第x 集存在的数对的数量。

说明

在样例2中可能的对数:

  1. x=1,y=2 (第1季第2集第2季第1集)
  2. x=2,y=3 (第2季第3集第3季第2集)
  3. x=1,y=3 (第1季第3集第3季第1集)

在样例3中:

  1. x=1,y=2 (第1季第2集第2季第1集)
  2. x=1,y=3 (第1季第3集第3季第1集)

感谢@月见之兔 提供的翻译

题目描述

One day Polycarp decided to rewatch his absolute favourite episode of well-known TV series "Tufurama". He was pretty surprised when he got results only for season 7 episode 3 with his search query of "Watch Tufurama season 3 episode 7 online full hd free". This got Polycarp confused — what if he decides to rewatch the entire series someday and won't be able to find the right episodes to watch? Polycarp now wants to count the number of times he will be forced to search for an episode using some different method.

TV series have n seasons (numbered 1 through n ), the i -th season has ai episodes (numbered 1 through ai ). Polycarp thinks that if for some pair of integers x and y ( x<y ) exist both season xepisode y and season yepisode x then one of these search queries will include the wrong results. Help Polycarp to calculate the number of such pairs!

输入输出格式

输入格式:

 

扫描二维码关注公众号,回复: 3658246 查看本文章

The first line contains one integer (1<=n<=2105) — the number of seasons.

The second line contains n integers separated by space a1,a2,...,an (1<=ai<=109) — number of episodes in each season.

 

输出格式:

 

Print one integer — the number of pairs x and y ( x<y ) such that there exist both season x episode y and season y episode x .

输入输出样例

输入样例#1: 复制
5
1 2 3 4 5
输出样例#1: 复制
0
输入样例#2: 复制
3
8 12 7
输出样例#2: 复制
3
输入样例#3: 复制
3
3 2 1
输出样例#3: 复制
2

说明

Possible pairs in the second example:

  1. x=1 , y=2 (season 1 episode 2  season 2 episode 1);
  2. x=2 , y=3 (season 2 episode 3  season 3 episode 2);
  3. x=1 , y=3 (season 1 episode 3  season 3 episode 1).

In the third example:

  1. x=1 , y=2 (season 1 episode 2  season 2 episode 1);
  2. x=1 , y=3 (season 1 episode 3  season 3 episode 1).

Solution

哭哭 多久没遇到这种不用看题解就能a掉的紫题了QAQ

一句话题意:求有多少对$<i,j>$,满足$a[i]>=j,a[j]>=i,i<j$

然后把关系再理一下,就变成了,对于每一个$i$,求在区间$[i+1,min(n,a[i])]$内有多少个$j$满足$a[j]>=i$

然后就是主席树叻~

倒着遍历维护每一个版本,查询区间就是用区间两个端点的版本满足条件的个数相减得到答案。

要离散化~

Code

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;

const int N = 200005;

int n, a[N], b[2 * N];

struct Node {
    Node *ls, *rs;
    int pos, val;
    void update() {
        val = ls -> val + rs -> val;
    }
} pool[32*N], *root[N], *tail = pool, *zero;

Node *newnode() {
    Node *nd = ++ tail;
    nd -> ls = zero;
    nd -> rs = zero;
    nd -> pos = 0;
    nd -> val = 0;
    return nd;
}

Node *build(int l, int r) {
    Node *nd = newnode();
    if(l == r)    return nd;
    int mid = (l + r) >> 1;
    nd -> ls = build(l, mid);
    nd -> rs = build(mid + 1, r);
    nd -> update();
    return nd;
}

int query(Node *nd, int l, int r, int L, int R) {
    if(l >= L && r <= R)    return nd -> val;
    int ans = 0; int mid = (l + r) >> 1;
    if(L <= mid)    ans += query(nd -> ls, l, mid, L, R);
    if(R > mid)        ans += query(nd -> rs, mid + 1, r, L, R);
    return ans;
}

Node *insert(Node *nd, int l, int r, int pos) {
    Node *nnd = newnode();
    if(l == r) {
        nnd -> val = nd -> val + 1; return nnd;
    }
    int mid = (l + r) >> 1;
    if(pos <= mid) {
        nnd -> rs = nd -> rs;
        nnd -> ls = insert(nd -> ls, l, mid, pos);
    } else {
        nnd -> ls = nd -> ls;
        nnd -> rs = insert(nd -> rs, mid + 1, r, pos);
    }
    nnd -> update();
    return nnd;
}

int main() {
    zero = ++ tail;
    zero -> ls = zero; zero -> rs = zero; zero -> pos = 0; zero -> val = 0;
    scanf("%d", &n);
    int t = 0;
    for(int i = 1; i <= n; i ++) {
        scanf("%d", &a[i]);
        b[++ t] = a[i]; b[++ t] = i;
    }
    sort(b + 1, b + 1 + t);
    int m = unique(b + 1, b + 1 + t) - b - 1;
    root[n + 1] = build(1, m);
    long long ans = 0;
    for(int i = n; i >= 1; i --) {
        int pos = lower_bound(b + 1, b + 1 + m, a[i]) - b;
        int posi = lower_bound(b + 1, b + 1 + m, i) - b;
        int R = min(n, pos);
        root[i] = insert(root[i + 1], 1, m, pos);
        if(R < i)    continue;
        int tmp1 = query(root[i + 1], 1, m, posi, m);
        int tmp2 = query(root[R + 1], 1, m, posi, m);
        ans += tmp1 - tmp2;
    }
    printf("%I64d", ans);
}

猜你喜欢

转载自www.cnblogs.com/wans-caesar-02111007/p/9824873.html