LOADING

加载过慢请开启缓存 浏览器默认开启

AtCoder Beginner Contest 372

D - Buildings

Problem Statement

There are $N$ buildings, Building $1$, Building $2$, $\ldots$, Building $N$, arranged in a line in this order. The height of Building $i$ $(1 \leq i \leq N)$ is $H_i$.

For each $i = 1, 2, \ldots, N$, find the number of integers $j$ $(i < j \leq N)$ satisfying the following condition:

  • There is no building taller than Building $j$ between Buildings $i$ and $j$.

Constraints

  • $1 \leq N \leq 2 \times 10^5$
  • $1 \leq H_i \leq N$
  • $ H_i\neq H_j\ (i\neq j)$
  • All input values are integers.

Sample Input 1

5
2 1 4 3 5

Sample Output 1

3 2 2 1 0

For $i=1$, the integers $j$ satisfying the condition are $2$, $3$, and $5$: there are three. (Between Buildings $1$ and $4$, there is a building taller than Building $4$, which is Building $3$, so $j=4$ does not satisfy the condition.) Therefore, the first number in the output is $3$.

实现

倒着将元素挨个放入单调栈,栈的元素个数即为当前位置的答案

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 2e5 + 10;
int a[N],b[N],c[N];
stack<int>st;
void solve(){
    int n;
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i];
    }
    for(int i=n;i>=1;i--){     
        b[i]=st.size();
        while(!st.empty()&&a[i]>st.top()){
            st.pop();
        }
        st.push(a[i]);
    }
    for(int i=1;i<=n;i++){
        cout<<b[i]<<' ';
    }
    cout<<endl;
}
signed main() {
    int t=1;
    //cin >> t;
    while (t--) {
        solve();
    }
       
}

E - K-th Largest Connected Components

Problem Statement

There is an undirected graph with $N$ vertices and $0$ edges. The vertices are numbered $1$ to $N$.

You are given $Q$ queries to process in order. Each query is of one of the following two types:

  • Type $1$: Given in the format 1 u v. Add an edge between vertices $u$ and $v$.

  • Type $2$: Given in the format 2 v k. Print the $k$-th largest vertex number among the vertices connected to vertex $v$. If there are fewer than $k$ vertices connected to $v$, print -1.

Constraints

  • $1 \leq N, Q \leq 2 \times 10^5$
  • In a Type $1$ query, $1 \leq u < v \leq N$.
  • In a Type $2$ query, $1 \leq v \leq N$, $1 \leq k \leq 10$.
  • All input values are integers.

Sample Input 1

4 10
1 1 2
2 1 1
2 1 2
2 1 3
1 1 3
1 2 3
1 3 4
2 1 1
2 1 3
2 1 5

Sample Output 1

2
1
-1
4
2
-1
  • In the first query, an edge is added between vertices $1$ and $2$.
  • In the second query, two vertices are connected to vertex $1$: $1$ and $2$. Among them, the $1$-st largest vertex number is $2$, which should be printed.
  • In the third query, two vertices are connected to vertex $1$: $1$ and $2$. Among them, the $2$-nd largest vertex number is $1$, which should be printed.
  • In the fourth query, two vertices are connected to vertex $1$: $1$ and $2$, which is fewer than $3$, so print -1.
  • In the fifth query, an edge is added between vertices $1$ and $3$.
  • In the sixth query, an edge is added between vertices $2$ and $3$.
  • In the seventh query, an edge is added between vertices $3$ and $4$.
  • In the eighth query, four vertices are connected to vertex $1$: $1,2,3,4$. Among them, the $1$-st largest vertex number is $4$, which should be printed.
  • In the ninth query, four vertices are connected to vertex $1$: $1,2,3,4$. Among them, the $3$-rd largest vertex number is $2$, which should be printed.
  • In the tenth query, four vertices are connected to vertex $1$: $1,2,3,4$, which is fewer than $5$, so print -1.

实现

启发式合并+平衡树查询

#include <bits/stdc++.h>
#include <bits/extc++.h>
using namespace __gnu_cxx;
using namespace __gnu_pbds;
using namespace std;
#define int long long
typedef tree<int, null_type, greater<int>, rb_tree_tag, tree_order_statistics_node_update> Tree;
const int N = 2e6 + 10;
Tree tr[N];
int f[N];
int find(int x){
    return f[x]==x?x:f[x]=find(f[x]);
}
void solve(){
    int n,q;
    cin>>n>>q;
    for(int i=1;i<=n;i++){
        tr[i].insert(i);
        f[i]=i;
    }
    for(int i=1;i<=q;i++){
        int st;
        cin>>st;
        if(st==1){
            int u,v;
            cin>>u>>v;
            u=find(u),v=find(v);
            if(u==v) continue;
            if(tr[u].size()>tr[v].size()){
                swap(u,v);
            }
            for(auto it:tr[u]){
                tr[v].insert(it);
                f[it]=v;
            }
            tr[u].clear();
        }
        else{
            int v,k;
            cin>>v>>k;
            v=find(v);
            if(tr[v].size()>=k){
                cout<<*tr[v].find_by_order(k-1)<<endl;
            }
            else{
                cout<<-1<<endl;
            }
        }
    }
}
signed main(){
    int t=1;
    //cin >> t;
    while (t--) {
        solve();
    } 
}