BZOJ 1803.Spoj1487 Query on a tree III

传送门

这一题一眼直接树剖 $+$ 主席树秒了,但是我并不想写这么麻烦的东西

所以我就开始琢磨换个简单的做法,发现可以离线,所以就想到了 $dsu\ on\ tree$

然后在想子树第 $k$ 大要怎么维护,感觉好像又要写什么数据结构,突然发现反正都是离线,直接 $sort$ 就完事了

然后就真的完事了,复杂度 $O(n( \log n)^2)$ ,SPOJ 由于电脑年代久远竟然 $T$ 飞了?本机测最大数据就 $0.1s$(为啥我会有数据呢)

在陈立杰神仙的 $ppt$ 里就可以看到对 SPOJ 的吐槽,由于某一题的哈希做法被卡常

(字符串长度只有 $1e5$),使得他 引入(发明?)了后缀自动机,所以现在才有这么多毒瘤后缀自动机毒瘤题...

(上图摘自陈立杰神仙的 $ppt$)

综上, $TLE$ 并不是我算法的问题....

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
using namespace std;
typedef long long ll;
inline int read()
{
    int x=0,f=1; char ch=getchar();
    while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
    while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
    return x*f;
}
const int N=2e5+7;
int fir[N],from[N<<1],to[N<<1],cntt;
inline void add(int a,int b) { from[++cntt]=fir[a]; fir[a]=cntt; to[cntt]=b; }
int n,m,a[N],ans[N];
int son[N],sz[N],pos[N],cnt;
struct poi{
    int id,val;
    poi (int a=0,int b=0) { id=a,val=b; }
    inline bool operator < (const poi &tmp) const {
        return val<tmp.val;
    }
};
vector <poi> tmp;
struct dat{
    int id,k;
    dat (int a=0,int b=0) { id=a,k=b; }
};
vector <dat> Q[N];
void dfs1(int x,int fa)
{
    sz[x]=1;
    for(int i=fir[x];i;i=from[i])
    {
        int &v=to[i]; if(v==fa) continue;
        dfs1(v,x); sz[x]+=sz[v];
        if(sz[v]>sz[son[x]]) son[x]=v;
    }
}
inline void calc(int x)
{
    int len=Q[x].size();
    for(int i=0;i<len;i++) ans[Q[x][i].id]=tmp[Q[x][i].k-1].id;
}
void dfs2(int x,int fa,bool type)
{
    pos[++cnt]=x; int L=cnt;
    if(!son[x]) { tmp.push_back(poi(x,a[x])); calc(x); if(!type) tmp.clear(); return; }
    for(int i=fir[x];i;i=from[i])
    {
        int &v=to[i]; if(v==fa||v==son[x]) continue;
        dfs2(v,x,0);
    }
    int R=cnt; dfs2(son[x],x,1);
    for(int i=L;i<=R;i++) tmp.push_back(poi(pos[i],a[pos[i]]));
    sort(tmp.begin(),tmp.end()); calc(x);
    if(!type) tmp.clear();
}
int main()
{
    n=read(); for(int i=1;i<=n;i++) a[i]=read();
    int u,v;
    for(int i=1;i<n;i++)
    {
        u=read(),v=read();
        add(u,v); add(v,u);
    }
    m=read(); for(int i=1;i<=m;i++) { u=read(),v=read(); Q[u].push_back(dat(i,v)); }
    dfs1(1,0); dfs2(1,0,1);
    for(int i=1;i<=m;i++) printf("%d\n",ans[i]);
    return 0;
}

 

猜你喜欢

转载自www.cnblogs.com/LLTYYC/p/11392318.html