有没有牛牛牛能解答一下为什么我的树套树会这么慢啊
查看原帖
有没有牛牛牛能解答一下为什么我的树套树会这么慢啊
433866
姐姐真可爱楼主2022/10/4 20:36
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
template<typename T>void read(T &x){
    x=0;int f(1);char c(getchar());
    for(;!isdigit(c);c=getchar())if(c=='-')f=-f;
    for(; isdigit(c);c=getchar())x=(x<<3)+(x<<1)+(c-'0');
    x*=f;
}
struct node{
    int a,b,c,id;
};
#define mid ((l+r)>>1)
#define ls node<<1
#define rs node<<1|1
#define endl '\n'
typedef  pair<pair<int,int>,int> piii;
typedef long long ll;
map<piii,int>ma;
node a[N];
bool cmp(node x1,node x2){
    if(x1.a!=x2.a) return x1.a<x2.a;
    if(x1.b!=x2.b) return x1.b<x2.b;
    return x1.c<x2.c;
}
const int V=2e5+10;
int n,k;
namespace treap{// 无旋treap (fhq-treap)
    const int N = 200007, INF = 0x3f3f3f3f;
    const int LOG=30;
    struct fhq_treap{
        int l, r;
        int size;
        int fa;
        int val, fix;
        ll sum;
    }tr[N*LOG];

    int cnt;
    int x, y, z, root[N<<2];

    inline void pushup(int p)
    {
        tr[p].size = tr[tr[p].l].size + tr[tr[p].r].size + 1;
        tr[p].sum = tr[tr[p].l].sum + tr[tr[p].r].sum + tr[p].val;
        tr[tr[p].l].fa = tr[tr[p].r].fa = p;
    }

    inline void split(int p, int k, int &x, int &y)//split_by_val
    {
        if(!p){x = y = 0; return ;}
        if(tr[p].val <= k)x = p, split(tr[p].r, k, tr[p].r, y);
        else y = p, split(tr[p].l, k, x, tr[p].l);
        pushup(p);
    }

    inline int merge(int x, int y)
    {
        if(!x || !y)return x + y;
        if(tr[x].fix > tr[y].fix){//小根堆
           tr[x].r = merge(tr[x].r, y);pushup(x);return x;
        }
        else {
            tr[y].l = merge(x, tr[y].l);pushup(y);return y;
        }
    }

    //!得到新节点
    inline int get_node(int val)
    {
        tr[++ cnt].size = 1;
        tr[cnt].fix = rand();
        tr[cnt].sum = tr[cnt].val = val;
        tr[cnt].fa = 0;
        return cnt;
    }

    //!树中插入新节点
    inline void my_insert(int k,int val)
    {
        split(root[k], val, x, y);
        root[k] = merge(merge(x, get_node(val)), y);
    }

    //!按值删除所有权值为k的所有点
    inline void my_delet_all(int k,int val)
    {
        split(root[k], val, x, z);
        split(x, val - 1, x, y);
        root[k] = merge(x, z);
        return ;
    }

    //!按值删除给定权值的一个点
    inline void my_delet_one(int k,int val)
    {
        split(root[k], val, x, z);
        split(x, val - 1, x, y);
        y = merge(tr[y].l, tr[y].r);
        root[k] = merge(merge(x, y), z);
        return ;
    }

    //!查询指定排名的一个数,返回那个数的编号
    inline int get_num_by_rank(int p, int k)
    {
        while(true){
            if(k <= tr[tr[p].l].size)p = tr[p].l;
            else if(k == tr[tr[p].l].size + 1)return p;
            else k -= tr[tr[p].l].size + 1, p = tr[p].r;
        }
    }

    //!按权值分裂时查询一个数的排名///

    //!根据权值查询一个数的排名
    inline int get_rank_by_val(int k,int val)
    {
        split(root[k], val - 1, x, y);
        int res = tr[x].size + 1;
        root[k] = merge(x, y);
        return res;
    }

    //!按排名分裂时查询一个数的排名/
    //!需要维护父节点

    //!根据编号查询这个数的排名
    inline int get_rank_by_num(int k,int p)
    {
        int res = tr[tr[p].l].size + 1;
        while(p != root[k]){//一直回溯
            if(p == tr[tr[p].fa].r)res += tr[tr[tr[p].fa].l].size + 1;
            p = tr[p].fa;
        }
        return res;
    }

    inline int get_val_by_rank(int k,int rank)
    {
        int res = tr[get_num_by_rank(root[k], rank)].val;
        return res;
    }


    //!查找前驱的编号
    //!按值查找比它小的数中的最大的数的编号
    inline int get_prev_of_num(int k,int val)
    {
        split(root[k], val - 1, x, y);
        int res = tr[get_num_by_rank(x, tr[x].size)].val;
        root[k] = merge(x, y);
        return res;
    }

    //!查找后继的编号
    //!按值查找比它大的数中最小数的编号
    inline int get_next_of_num(int k,int val)
    {
        split(root[k], val, x, y);
        int res = tr[get_num_by_rank(y, 1)].val;
        root[k] = merge(x, y);
        return res;
    }

    //!查找节点的祖先节点
    inline int get_anc(int x)
    {
        while(tr[x].fa){
            x = tr[x].fa;
        }
        return x;
    }


    inline void main()
    {
        srand((unsigned)time(NULL));
        memset(tr, 0, sizeof tr);
        cnt = 0;
    }
}

void insert(int node,int l,int r,int x,int v){
    treap::my_insert(node,v);
    if(l==r) return;
    if(x<=mid) insert(ls,l,mid,x,v); 
    else insert(rs,mid+1,r,x,v);
}

int query(int node,int l,int r,int ql,int qr,int val){//<=val
    // cout<<node<<" "<<l<<" "<<r<<endl;
    if(ql<=l&&r<=qr){
        return treap::get_rank_by_val(node,val+1)-1;
        return 0;
    }
    int ans=0;
    if(ql<=mid) ans+=query(ls,l,mid,ql,qr,val);
    if(qr>mid ) ans+=query(rs,mid+1,r,ql,qr,val);
    return ans;
}

int ans1[N];
int ans2[N];

int main(){
    srand(time(0));
    read(n),read(k);
    for(int i=1;i<=n;i++) {
        read(a[i].a),read(a[i].b),read(a[i].c);a[i].id=i;
        }
    sort(a+1,a+1+n,cmp);
    for(int i=1;i<=n;i++){
        int tmp=query(1,0,V,0,a[i].b,a[i].c);
        ma[{{a[i].a,a[i].b},a[i].c}]++;
        ans1[i]=tmp;
        insert(1,0,V,a[i].b,a[i].c);
    }
    for(int i=1;i<=n;i++){
        ans1[i]+=ma[{{a[i].a,a[i].b},a[i].c}]-1;
        ma[{{a[i].a,a[i].b},a[i].c}]-=1;
        ans2[ans1[i]]++;
    }
    for(int i=0;i<n;i++){
        cout<<ans2[i]<<endl;
    }
}

代码如上,t了4个点

2022/10/4 20:36
加载中...