CodeForces:Nested Segments

265 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第14天,点击查看活动详情

题目描述

这是codeforces的线段树专题。

C - Segment Tree, part 1 - Nested Segments

Given an array of 2n numbers, each number from 1 to n in it occurs exactly twice. We say that the segment y is nested inside the segment x if both occurrences of the number y are between the occurrences of the number x. Find for each segment ii how many segments that are nested inside it.

Input

The first line contains the number n (1≤n≤10^5), the second line contains 2n numbers. It is guaranteed that every number from 1 to n occurs exactly twice.

Output

Print n numbers, the i-th number is equal to the number of segments nested inside the segment i.

Example

input

5
5 1 2 2 3 1 3 4 5 4

output

1 0 0 0 3 

问题解析

这题意思是说,有2n个数,数组是由1~n组成的,每个数有两个,相同的两个数被称作一段,问你一个段里包含了多少段,比如5和5之间包括了1、2、3段,4不算,因为4的右端在外面。

一开始先准备一个叶子全为0的线段树。我们从左往右走,先记录下每个段的左端的下标,当走到右端的时候,记录左端到右端这一段区间的区间和,区间和为多少,说明里面有多少段。计算完区间和后,我们把左段点的位置从0变成1。

首先,我们只有走完了一个段的左端和右端后,我们才会把这个段的左端点的值从0变成1。如果我们一个段的区间和不为0,那么区间和为几,就说明里面已经包含了多少完整的段。如果只包含了左端点,那么还没走到右端点,左端点的值依然是0,如果只包含右端点,但我们只把左端点的值变成了1,所以右端点也不会被记上。

#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<math.h>
#include<set>
#include<numeric>
#include<string>
#include<string.h>
#include<iterator>
#include<map>
#include<unordered_map>
#include<stack>
#include<list>
#include<queue>
#include<iomanip>

#define endl '\n';
typedef long long ll;
typedef pair<int, int> PII;
const int N = 300050;
int f[4 * N], a[N], n;

void revise(int k, int l, int r, int x)
{
    if (l == r)
    {
        f[k] = 1;
        return;
    }
    int m = (l + r) / 2;
    if (x <= m)revise(k + k, l, m, x);
    else
        revise(k + k + 1, m + 1, r, x);
    f[k] = f[k + k] + f[k + k + 1];
}

int calc(int k, int l, int r, int x, int y)
{
    if (l == x && y == r)
    {
        return f[k];
    }
    int m = (l + r) / 2;
    if (y <= m)return calc(k + k, l, m, x, y);
    else
        if (x > m)return calc(k + k + 1, m + 1, r, x, y);
        else return calc(k + k , l, m, x, m) + calc(k + k+1, m + 1, r, m + 1, y);
}

int main()
{
    unordered_map<int, int>mymap;
    map<int, int>cnt;
    cin >> n;
    for (int i = 1; i <= 2*n; i++)
    {
        cin >> a[i];
        if (mymap[a[i]] == 0)mymap[a[i]] = i;
    }
    for (int i = 1; i <= 2*n; i++)
    {
        if (cnt[a[i]] == 0)
            cnt[a[i]] = 1;
        else
        {
            cnt[a[i]] = calc(1, 1, 2*n, mymap[a[i]], i);
            revise(1, 1, 2*n, mymap[a[i]]);

        }
    }
    for (auto i : cnt)cout << i.second << " ";
    return 0;
}