#790 div4

G

#include<bits/stdc++.h>
#include <ostream>

using namespace std;
typedef long long ll;
#define endl '\n'
typedef pair<int, int> PII;
#define debug() cout.flush()
#define for0(i, a) for (int i = 0; i < a; ++i)
#define REP(i, a, b)  for (int i = a; i < b; ++i)
#define FOR(i, a, b)  for (int i = a; i <= b; ++i)
#define REPC(i, a, b, c)  for (ll i = a; i < b && i < c; ++i)
#define RREP(i, a, b) for (int i = a; i >= b; --i)
const ll MOD = 1e9 + 7;
const ll mod = 998244353;
const int INF = 0x3f3f3f3f;
const int MAXN = 3e5 + 5e3;

inline void init() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
}

ll n, m, q;
int op[MAXN];
vector<int>v[4050];
string s;
int ans;

inline int dfs(int x) { 
	int res = op[x];
    int len = v[x].size();
    for (int i = 0; i < len; i++) { //记录整个数的权值
    	res += dfs(v[x][i]);
    }
    if (!res) ans++; //为0表示黑白相等
    return res;
}

inline void solve() {
    cin >> n;
    for (int i = 0; i <= n; i++) v[i].clear();
    for (int i = 2; i <= n; i++) {
        int pos;
        cin >> pos;
        v[pos].push_back(i); //建树
    }
    cin >> s;
    for (int i = 0; i < n; i++) {
        op[i + 1] = (s[i] == 'W' ? 1 : -1); //赋初值
    }
    ans = 0;
    dfs(1);
    cout << ans << endl;
}

signed main() {
    init();
    int t;
    cin >> t;
    while (t--) {
        solve();
    }
    return 0;
}

H
维护当前点后面有多少个小于等于当前点的值(记录每个值的点的个数,然后用线段树维护前缀和,每次经过点后将点删除)

#include<bits/stdc++.h>
#include <ostream>

using namespace std;
typedef long long ll;
#define endl '\n'
typedef pair<int, int> PII;
#define debug() cout.flush()
#define for0(i, a) for (int i = 0; i < a; ++i)
#define REP(i, a, b)  for (int i = a; i < b; ++i)
#define FOR(i, a, b)  for (int i = a; i <= b; ++i)
#define REPC(i, a, b, c)  for (ll i = a; i < b && i < c; ++i)
#define RREP(i, a, b) for (int i = a; i >= b; --i)
const ll MOD = 1e9 + 7;
const ll mod = 998244353;
const int INF = 0x3f3f3f3f;
const int MAXN = 3e5 + 5e3;

inline void init() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
}

ll n, m, q;
ll sum[MAXN << 2], num[MAXN], a[MAXN];

inline void pushup(int x) {
    sum[x] = sum[x << 1] + sum[x << 1 | 1];
}

inline void build(int l = 1, int r = n, int x = 1) {
    if (l == r) {
        sum[x] = num[l];
        return;
    }
    int mid = l + r >> 1;
    build(l, mid, x << 1);
    build(mid + 1, r , x << 1 | 1);
    pushup(x);
}

inline void update(int l, int r, int x, int qx) {
    if (l == r) {
        sum[x]--;
        return;
    }
    int mid = l + r >> 1;
    if (qx <= mid) update(l, mid, x << 1, qx);
    else update(mid + 1, r, x << 1 | 1, qx);
    pushup(x);
}

inline ll query(int l, int r, int x, int ql, int qr) {
    if (l >= ql && r <= qr) {
        return sum[x];
    }
    int mid = l + r >> 1;
    ll res = 0;
    if (ql <= mid) res += query(l, mid, x << 1, ql, qr);
    if (qr > mid) res += query(mid + 1, r, x << 1 | 1, ql, qr);
    return res;
}

inline void solve() {
    cin >> n;
    for0 (i, n + 1) num[i] = 0;
    for0 (i, n) cin >> a[i], num[a[i]]++;
    ll res = 0;
    build();
    for0 (i, n) {
        update(1, n, 1, a[i]);
        res += query(1, n, 1, 1, a[i]);
    }
    cout << res << endl;
}

signed main() {
    init();
    int t;
    cin >> t;
    while (t--) {
        solve();
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值