luogu 5311 [Ynoi2011]D1T3 动态点分治+树套树

我这份代码已经奇怪到一定程度了~

洛谷上一直 $TLE$,但是本地造了几个数据都过了.

// luogu-judger-enable-o2
#include <bits/stdc++.h>   
#define N 1000005     
#define inf 100001
#define setIO(s) freopen(s".in","r",stdin)    , freopen(s".out","w",stdout)      
using namespace std;  
char *p1,*p2,buf[100000];
#define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
int rd() {int x=0; char c=nc(); while(c<48) c=nc(); while(c>47) x=(((x<<2)+x)<<1)+(c^48),c=nc(); return x;}
int edges,n,flag; 
int hd[N],to[N<<1],nex[N<<1],val[N],rt[N<<2];  
void add(int u,int v) 
{
    nex[++edges]=hd[u],hd[u]=edges,to[edges]=v; 
}
namespace segin
{  
    #define lson  t[x].ls 
    #define rson t[x].rs 
    int tot;  
    struct Node
    {
        int ls,rs,sum; 
    }t[N*100];   
    void update(int &x,int l,int r,int p,int v) 
    {
        if(!x) x=++tot;           
        t[x].sum+=v; 
        if(l==r) return; 
        int mid=(l+r)>>1;    
        if(p<=mid) update(lson,l,mid,p,v); 
        else update(rson,mid+1,r,p,v);    
    }   
    int query(int x,int l,int r,int L,int R) 
    { 
        if(!x) return 0; 
        if(l>=L&&r<=R) return t[x].sum; 
        int mid=(l+r)>>1,re=0;  
        if(L<=mid) re+=query(lson,l,mid,L,R); 
        if(R>mid)  re+=query(rson,mid+1,r,L,R); 
        return re; 
    } 
    void re()  
    { 
        for(int i=1;i<=tot;++i) 
            t[i].ls=t[i].rs=t[i].sum=0;  
        tot=0; 
    }
    #undef lson 
    #undef rson 
};  
namespace segout
{ 
    #define lson (now<<1) 
    #define rson (now<<1|1) 
    vector<int>g;     
    int vis[N*100]; 
    void update(int l,int r,int now,int x,int y,int v) 
    {
        segin::update(rt[now],0,n,y,v);  
        if(!vis[now]) vis[now]=1, g.push_back(now);    
        if(l==r) return;   
        int mid=(l+r)>>1;    
        if(x<=mid) update(l,mid,lson,x,y,v); 
        else update(mid+1,r,rson,x,y,v);       
    }
    int query(int l,int r,int now,int L,int R,int L2,int R2) 
    {
        if(l>=L&&r<=R) 
            return segin::query(rt[now],0,n,L2,R2);                          
        int mid=(l+r)>>1,re=0; 
        if(L<=mid) re+=query(l,mid,lson,L,R,L2,R2); 
        if(R>mid)  re+=query(mid+1,r,rson,L,R,L2,R2);    
        return re;   
    } 
    void re() 
    {
        for(int i=0;i<g.size();++i) 
            vis[g[i]]=rt[g[i]]=0;    
        g.clear();    
    }
    #undef lson 
    #undef rson 
};     
struct Node 
{
    int l,r,x;     
    Node(int l=0,int r=0,int x=0):l(l),r(r),x(x){}     
}; 
vector<Node>e[N];     
struct Point 
{
    int l,r,id,val; 
    Point(int l=0,int r=0,int id=0,int val=0):l(l),r(r),id(id),val(val){}   
};       
vector<Point>F[N];    
bool cmp(Point a,Point b) 
{
    return a.l==b.l?a.id>b.id:a.l>b.l;                   
}
int root,sn; 
int mx[N],size[N],vis[N],Fa[N],answer[N],lsty[N],lstx[N];       
void dfs(int u,int ff) 
{
    size[u]=1; 
    for(int i=hd[u];i;i=nex[i]) 
        if(to[i]!=ff&&!vis[to[i]]) 
            dfs(to[i],u),size[u]+=size[to[i]];     
}
void getroot(int u,int ff) 
{
    size[u]=1,mx[u]=0;  
    for(int i=hd[u];i;i=nex[i]) 
        if(to[i]!=ff&&!vis[to[i]]) 
            getroot(to[i],u),size[u]+=size[to[i]],mx[u]=max(mx[u],size[to[i]]); 
    mx[u]=max(mx[u],sn-size[u]);    
    if(mx[u]<mx[root]) root=u;
} 
void calc(int u,int ff,int Min,int Max,int rt) 
{
    Min=min(Min,u),Max=max(Max,u); 
    F[rt].push_back(Point(Min,Max,u,val[u])), e[u].push_back(Node(Min,Max,rt));     
    for(int i=hd[u];i;i=nex[i]) 
        if(!vis[to[i]]&&to[i]!=ff) 
            calc(to[i],u,Min,Max,rt); 
}
void prepare(int u) 
{
    vis[u]=1; 
    calc(u,0,u,u,u); 
    for(int i=hd[u];i;i=nex[i]) 
        if(!vis[to[i]]) 
            dfs(to[i],u),sn=size[to[i]],root=0,getroot(to[i],u),Fa[root]=u,prepare(root);         
} 
void Push(int u,int l,int r,int id) 
{
    for(int i=0;i<(int)e[u].size();++i) 
    {
        if(e[u][i].l>=l&&e[u][i].r<=r)  
        {
            F[e[u][i].x].push_back(Point(l,r,-1,id)); 
            break; 
        }
    } 
}          
void solve(int u) 
{   
    int i,j; 
    sort(F[u].begin(),F[u].end(),cmp);   
    for(i=0;i<(int)F[u].size();++i) 
    { 
        Point p=F[u][i];      
        if(p.id==-1) 
            answer[p.val]=segout::query(0,n,1,p.l,p.r,p.l,p.r);        
        else
        {   
            if(!lsty[p.val]||p.r<=lsty[p.val]) 
            {             
                if(lsty[p.val]) segout::update(0,n,1,lstx[p.val],lsty[p.val],-1);    
                segout::update(0,n,1,p.l,p.r,1);    
                lstx[p.val]=p.l, lsty[p.val]=p.r;                  
            }
        }
    }   
    for(i=0;i<(int)F[u].size();++i) 
        if(F[u][i].id!=-1) 
            lstx[F[u][i].val]=lsty[F[u][i].val]=0;     
    segin::re();    
    segout::re();   
}
int main() 
{ 
    int i,j,m; 
    // setIO("input"); 
    n=rd(),m=rd(); 
    for(i=1;i<=n;++i) val[i]=rd(); 
    for(i=1;i<n;++i) 
    {
        int x,y; 
        x=rd(),y=rd(),add(x,y),add(y,x); 
    }
    root=0,mx[0]=sn=n,getroot(1,0),prepare(root);    
    for(i=1;i<=m;++i) 
    {                  
        int l,r,x; 
        l=rd(),r=rd(),x=rd(),Push(x,l,r,i);                   
    }             
    for(i=1;i<=n;++i) if(F[i].size()) solve(i);       
    for(i=1;i<=m;++i) printf("%d\n",answer[i]);                                   
    return 0; 
}   

  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值