主席树95分

P3899 [湖南集训] 更为厉害

Digital_Sunrise @ 2024-07-09 10:29:10

O2TLE

不开就 MLE

试过在不开的情况下只把一点点变量改成 long long 没什么用

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int _ = 3e5 + 5;

inline int read()
{
    int w = 1,f = 0;
    char c = getchar();
    while(c < '0' or c > '9'){if(c == '-') w = -1;c = getchar();}
    while(c >= '0' and c <= '9'){f = f * 10 + c - '0';c = getchar();}
    return w * f;
}

struct node
{
    int l,r,ls,rs,sum;
    node(){l = r = ls = rs = sum = 0;}
    node(int _l,int _r,int _ls,int _rs,int _sum):l(_l),r(_r),ls(_ls),rs(_rs),sum(_sum){}
}a[_ << 5];

int n,q;
vector <int> G[_];
int siz[_],dep[_],dfn[_],_dfn;
int init[_],cnt,rt[_];

void dfs(int u,int fa)
{
//  cout << "FUCKING " << u << " " << fa << endl;

    dep[u] = dep[fa] + 1;
    dfn[u] = ++_dfn;
    siz[u] = 1;
    for(int v : G[u])
    {
        if(v == fa)
            continue;
        dfs(v,u);
        siz[u] += siz[v];
    }
}

int build(int l,int r)
{
    int k = ++cnt;
    a[k].l = l,a[k].r = r;
    if(l == r) return k;
    int mid = (l + r) >> 1;
    a[k].ls = build(l,mid);
    a[k].rs = build(mid + 1,r);
    return k;
}

int update(int pre,int x,int y)
{
    int k = ++cnt;
    a[k] = a[pre];
    if(a[k].l == a[k].r)
    {
        a[k].sum += y;
        return k;
    }
    int mid = (a[k].l + a[k].r) >> 1;
    if(x <= mid)
        a[k].ls = update(a[k].ls,x,y);
    if(x > mid)
        a[k].rs = update(a[k].rs,x,y);
    a[k].sum = a[a[k].ls].sum + a[a[k].rs].sum;
    return k;
}

int query(int k,int l,int r)
{
//  if(k == 0)
//      exit(0);
//  cout << k << " " << a[k].l << " " << a[k].r << endl;
    if(a[k].l >= l and a[k].r <= r)
        return a[k].sum;
    int mid = (a[k].l + a[k].r) >> 1,sum = 0;
    if(l <= mid)
        sum += query(a[k].ls,l,r);
    if(r > mid)
        sum += query(a[k].rs,l,r);
    return sum;
}

signed main()
{
    n = read();
    q = read();
    for(int i = 1;i < n;i++)
    {
        int u,v;
        u = read();
        v = read();
        G[u].push_back(v);
        G[v].push_back(u);
    }
    dfs(1,0);
    for(int i = 1;i <= n;i++)
        init[dfn[i]] = i;
    //_______________________________
//  cout << "dfn: ";
//  for(int i = 1;i <= n;i++)
//      cout << dfn[i] << " ";
//  cout << endl << "init:";
//  for(int i = 1;i <= n;i++)
//      cout << init[i] << " ";
//  cout << endl;
    //_______________________________
    rt[0] = build(1,n);
    for(int i = 1;i <= n;i++)
        rt[i] = update(rt[i - 1],dep[init[i]],siz[init[i]] - 1)/*,printf("FUCKing : %d - > %d \n",i,query(rt[i],1,4))*/;
    while(q--)
    {
        int p = read(),k = read(),ans = 0;

        ans += min(dep[p] - 1,k) * (siz[p] - 1);
//      cout << "FUCK1 " << query(rt[dfn[p] + siz[p] - 1],1,4) << endl;
//      cout << "FUCK2 " << query(rt[dfn[p]],1,4) << endl;
        ans += query(rt[dfn[p] + siz[p] - 1],dep[p] + 1,dep[p] + k);
        ans -= query(rt[dfn[p]],             dep[p] + 1,dep[p] + k);//bug : dep[p + 1];
        printf("%lld\n",ans);
    }
    return 0;
}

by Kapo_Hisy @ 2024-07-09 10:41:47

用define卡O3+快写+变量参数不用修改的用const+ans修改那一段合并一下。

可能会有加速(但不多)。

@Digital_Sunrise


by Digital_Sunrise @ 2024-07-09 10:49:31

@Kapo_Hisy

O3 被 OJ 拒收了。。


by Kapo_Hisy @ 2024-07-09 10:55:05

#define optimize qwq
#pragma GCC qwq(3)

我平时卡常用这个没问题的呀,奇怪了。@Digital_Sunrise


by Kapo_Hisy @ 2024-07-09 10:56:24

这好像不是RemoteJudge,似乎是没问题的,我有些P前缀题目卡常这样写似乎没问题。


by Digital_Sunrise @ 2024-07-09 11:04:04

@Kapo_Hisy 大佬能不能帮我分析一下

6年前有一个前辈通过加入了 query 函数第一行的特判从95改到了AC


ll query(int id1,int id2,int l,int r,int ql,int qr){
    if(ql>qr) return 0;
    if(l==ql&&r==qr) return t[id2].val-t[id1].val;
    int mid=(l+r)/2;
    if(qr<=mid) return query(t[id1].lch,t[id2].lch,l,mid,ql,qr);
    else if(ql>mid) return query(t[id1].rch,t[id2].rch,mid+1,r,ql,qr);
    else return query(t[id1].lch,t[id2].lch,l,mid,ql,mid)+query(t[id1].rch,t[id2].rch,mid+1,r,mid+1,qr);
}

但是我的写法似乎和主流不同,所以我并不知道我的 query 有没有问题、怎么改

这是我的:

ll query(int k,int l,int r)
{
//  if(k == 0)
//      exit(0);
//  cout << k << " " << a[k].l << " " << a[k].r << endl;
    if(a[k].l >= l and a[k].r <= r)
        return a[k].sum;
    int mid = (a[k].l + a[k].r) >> 1;
    ll sum = 0;
    if(l <= mid)
        sum += query(a[k].ls,l,r);
    if(r > mid)
        sum += query(a[k].rs,l,r);
    return sum;
}

by Kapo_Hisy @ 2024-07-09 11:06:28

@Digital_Sunrise 不好意思,我看主站点进来的,我不会主席树()主要是我看()一下如何卡过(卡常方法


by Kapo_Hisy @ 2024-07-09 11:07:08

后面的部分基本一致,就多了一个判断。


by Kapo_Hisy @ 2024-07-09 11:10:03

第一个特判明显是对的,但不过加上去因该是因为有可能数据会卡到l>r的情况


by Digital_Sunrise @ 2024-07-09 12:47:05

先给解决方法

query 中加入 k == 0 的特判

如果不是我这种解法就加入 ql > qr 的特判


|