码迷,mamicode.com
首页 > 其他好文 > 详细

wangdy带佬给的权值线段树模板

时间:2019-11-04 17:15:21      阅读:71      评论:0      收藏:0      [点我收藏+]

标签:ons   长度   启发式   pre   name   getch   线段   and   include   

实为1027练习题C-遥色点对题解

给出一张由编号1到n的n个点和m条边构成的无向图。每条边都有一定的长度。 定义,一条路径的“代价”:该路径上最长一条边的长度。 定义,点x到点y的“点距”:点x到点y的最小代价。 图中每个点都被涂上了颜色,第i号点的颜色编号为Ci。 满足x<y 且|Cx-Cy|>=K 的任意一对点(x,y)都被称为“遥色点对”

现在需要你求出图中所有遥色点对的点距之和。

动态开点线段树启发式合并

#include<stdio.h> 
#include<bits/stdc++.h> 
#define f(a,b,c) for(register int a=(b);a<=(c);++a) 
#define ff(a,b,c) for(register int a=(b);a>=(c);--a) 
#define ll long long 
#define max(a,b) ((a)>(b)?(a):(b)) 
//#define int long long 
char pbuf[1<<20],*pp1=pbuf; 
inline void push(char c){*pp1=c;pp1=(pp1-pbuf==(1<<20)-1)?(fwrite(pbuf,1,1<<20,stdout),pbuf):(pp1+1);} 
//#define pc push 
#define pc putchar 
#define pe pc('\n') 
#define ps pc(' ') 
#define wer rd() 
char *p1,*p2,buf[1<<20]; 
#define GC (p1==p2&&(p1=buf,p2=buf+fread(buf,1,1<<20,stdin),p1==p2)?0:(*(p1++))) 
//#define GC getchar() 
using namespace std; 
inline ll wer{ 
    ll ans;char t,k; 
    while(((t=GC)!='-')&&(t>'9'||t<'0')); 
    k=(t=='-'); 
    ans=k?0:(t-'0'); 
    while((t=GC)>='0'&&t<='9')ans=ans*10+t-'0'; 
    return k?-ans:ans; 
} 
inline void wt(ll k) 
{ 
    if(k<0)pc('-'),wt(-k); 
    else 
    { 
        if(k<10)pc('0'+k); 
        else wt(k/10),pc('0'+k%10); 
    } 
    return; 
} 
const int N=2e5+5; 
int n,m,K; 
int ck[N<<5],k[N<<5],ls[N<<5],rs[N<<5],rt[N],tot; 
int build(int l,int r,int x) 
{ 
    if(r<x||x<l)return 0; 
    int now=ck[tot--]; 
    if(l==r){k[now]=1;return now;} 
    int mid=l+r>>1; 
    ls[now]=build(l,mid,x); 
    rs[now]=build(mid+1,r,x); 
    k[now]=k[ls[now]]+k[rs[now]]; 
    return now; 
} 
int merge(int x,int y,int l,int r)//merge y to x and delete y 
{ 
    if(y==0)return x; 
    if(x==0)x=ck[tot--],k[x]=0,ls[x]=0,rs[x]=0; 
    if(l==r){ 
        k[x]+=k[y]; 
        k[y]=0; 
        ck[++tot]=y; 
        return x; 
    } 
    int mid=l+r>>1; 
    ls[x]=merge(ls[x],ls[y],l,mid); 
    rs[x]=merge(rs[x],rs[y],mid+1,r); 
    k[x]=k[ls[x]]+k[rs[x]]; 
    k[y]=0; 
    ck[++tot]=y; 
    return x; 
} 
int sum(int now,int l,int r,int x,int y) 
{ 
    if(!now||y<x)return 0; 
    if(r<x||y<l)return 0; 
    if(x<=l&&r<=y)return k[now]; 
    int mid=l+r>>1; 
    return sum(ls[now],l,mid,x,y)+sum(rs[now],mid+1,r,x,y); 
} 
#define maxn 1000000000 
int ans=0; 
void countans(int now,int l,int r,int to) 
{ 
    if(!now)return; 
    if(l==r) 
    { 
        if(K==0)ans+=k[now]*k[to]; 
        else ans+=k[now]*(sum(to,1,maxn,1,l-K) 
        +sum(to,1,maxn,l+K,maxn)); 
        return; 
    } 
    int mid=l+r>>1; 
    countans(ls[now],l,mid,to); 
    countans(rs[now],mid+1,r,to); 
    return; 
} 
void get(int now,int l,int r) 
{ 
    if(!now)return; 
    if(l==r)wt(l),ps; 
    else get(ls[now],l,(l+r>>1)),get(rs[now],(l+r>>1)+1,r); 
} 
vector<pair<int,pair<int,int> > >v; 
int c[N]; 
int f[N]; 
int getf(int x){return f[x]==x?x:(f[x]=getf(f[x]));} 
main() 
{ 
    n=wer,m=wer,K=wer; 
    f(i,1,n<<5|1)ck[++tot]=i; 
    f(i,1,n)c[i]=wer,f[i]=i,rt[i]=build(1,maxn,c[i]); 
//    f(i,1,n)get(rt[i],1,maxn),pe; 
//    cout<<"sdjadsff\n"; 
    f(i,1,m) 
    { 
        int a=wer,b=wer,c=wer; 
        v.push_back({c,{a,b}}); 
    } 
    sort(v.begin(),v.end()); 
    if(v[0].first>v[v.size()-1].first)reverse(v.begin(),v.end()); 
    int Ans=0; 
    f(i,0,m-1) 
    { 
        int a=getf(v[i].second.first); 
        int b=getf(v[i].second.second); 
        if(a==b)continue; 
        if(k[rt[a]]<k[rt[b]])swap(a,b); 
        f[b]=a; 
//        cout<<"now merge "<<a<<" to "<<b<<endl; 
//        cout<<"sizeof "<<a<<":"<<k[rt[a]]<<"\n"; 
//        cout<<"sizeof "<<b<<":"<<k[rt[b]]<<"\n"; 
//        cout<<"what in "<<a<<":\n";get(rt[a],1,maxn);pe; 
//        cout<<"what in "<<b<<":\n";get(rt[b],1,maxn);pe; 
        ans=0; 
        countans(rt[b],1,maxn,rt[a]); 
        rt[a]=merge(rt[a],rt[b],1,maxn); 
//        cout<<"now check tree "<<a<<"\n"; 
//        get(rt[a],1,maxn);pe; 
        Ans+=ans*v[i].first; 
    } 
     
//    wt(k[rt[getf(2)]]),pe; 
    wt(Ans);  
    fwrite(pbuf,1,pp1-pbuf,stdout); 
    return 0; 
}

wangdy带佬给的权值线段树模板

标签:ons   长度   启发式   pre   name   getch   线段   and   include   

原文地址:https://www.cnblogs.com/cooper233/p/11792835.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!