結果
| 問題 |
No.778 クリスマスツリー
|
| コンテスト | |
| ユーザー |
naribow
|
| 提出日時 | 2020-09-22 10:27:05 |
| 言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 161 ms / 2,000 ms |
| コード長 | 2,363 bytes |
| コンパイル時間 | 1,621 ms |
| コンパイル使用メモリ | 172,724 KB |
| 実行使用メモリ | 32,128 KB |
| 最終ジャッジ日時 | 2024-06-25 21:15:22 |
| 合計ジャッジ時間 | 4,234 ms |
|
ジャッジサーバーID (参考情報) |
judge3 / judge4 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 |
| other | AC * 12 |
ソースコード
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const double pi=3.141592653589793;
typedef unsigned long long ull;
typedef long double ldouble;
const ll INF=1e18;
#define rep(i, n) for(ll i = 0; i < (ll)(n); i++)
#define rep2(i, s, n) for (ll i = (s); i < (ll)(n); i++)
template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; }
class BIT {
public:
ll n; //データの長さ
vector<ll> bit; //データの格納先
BIT(ll n):n(n),bit(n+1,0){} //コンストラクタ
//k & -kはLSB
//bit_iにxをO(log(n))で加算する
void add(ll i,ll x){
if(i==0) return;
for(ll k=i;k<=n;k+=(k & -k)){
bit[k]+=x;
}
}
//bit_1 + bit_2 + … + bit_n をO(log(n))で求める
ll sum(ll i){
ll s=0;
if(i==0) return s;
for(ll k=i;k>0;k-=(k & -k)){
s+=bit[k];
}
return s;
}
//a_1 + a_2 + … + a_i >= x となるような最小のiを求める(a_k >= 0)
//xが0以下の場合は該当するものなし→0を返す
ll lower_bound(ll x){
if(x<=0){
return 0;
}else{
ll i=0;ll r=1;
//最大としてありうる区間の長さを取得する
//n以下の最小の二乗のべき(BITで管理する数列の区間で最大のもの)を求める
while(r<n) r=r<<1;
//区間の長さは調べるごとに半分になる
for(int len=r;len>0;len=len>>1) {
//その区間を採用する場合
if(i+len<n && bit[i+len]<x){
x-=bit[i+len];
i+=len;
}
}
return i+1;
}
}
};
vector<vector<int> > G(200010);
BIT bit(200010);
ll ans = 0;
void dfs (int cu, int pa) {
bit.add(cu, 1);
ans += bit.sum(cu);
rep(i, G[cu].size()) {
int to = G[cu][i];
if(to != pa) {
dfs(to, cu);
}
}
bit.add(cu, -1);
return;
}
int main() {
int n;
cin >> n;
vector<int> a(n);
rep2(i, 1, n) {
cin >> a[i];
G[a[i]].push_back(i);
G[i].push_back(a[i]);
}
dfs(0, -1);
cout << ans << endl;
}
naribow