【解不出来】【莫队】【多校】This world need more Zhu HDU5799

(弄了一个月的搬瓦工搭个梯子顺便搭个博客玩……不务正业)


题目描述

As we all know, Zhu is the most powerful man. He has the infinite power to protest the world. We need more men like Zhu!
In Duoladuo, this place is like a tree. There are n points and n1 edges. And the root is 1 . Each point can reach other points. Each point has a value a[i] named Zhu power.
Liao is a curious baby, he has m questions to ask Zhu. But now Zhu is busy, he wants you to help him answer Liao’s questions.
Liao’s question will be like op u v a b.
if op is 1, the u is equal to v . Liao wants to know the gcd of the sum of numbers thats appears a times and the sum of numbers that appears b times in subtree u .
if op is 2, Liao wants to know the gcd of the sum of numbers thats appears a times and the sum of numbers that appears b times on the path from u to v .
gcd is greatest common divisor.
notice: we can know gcd(x,0)=x .

输入

In the first line contains a single positive integer T , indicating number of test case.
In the second line there are two numbers n,m . n is the size of Duoladuo. m is the number of Liao’s questions.
The next line contains n integers A1,A2,AN , means the value of i point.
In the next n1 line contains tow numbers u,v . It means there is a edge between point u and point v .
The next m lines will be the Liao’s question:
1 u v a b
2 u v a b
1T10,1n100000,1m100000,1op2,1u,vn,1a,bn,1Ai1000000000 .

输出

For each case, output Case #i:. ( i is the number of the test case, from 1 to T ).
Then, you need to output the answer for every Liao’s questions.

样例输入

1
5 5
1 2 4 1 2
1 2
2 3
3 4
4 5
1 1 1 1 1
1 1 1 1 2
2 1 5 1 1
2 1 5 1 2
2 1 1 2 2

样例输出

Case #1:
4
1
4
1
0

对于操作1只要搞出来树的dfs序,每个询问对应一个连续区间,直接做序列莫队即可。
对于操作2就是树上莫队。
然后我按照之前的做法在搞出的括号序上跑莫队,T了。Baidu到一篇博客也说本地测10s,根本卡不过去。看了一下数据,后面五个点的莫队基本上都跑满了 nn 。本来 n 给的范围就很大了,然后对于这种专门构造数据卡某种算法的我也是无Fuck说。那种树分块的暂时还不会,以后学一下。
另外那篇博客说做两次常数大其实不然,想一下也是分开做复杂度更优。
下面就贴个一起做的代码吧,写的还算比较短,不过很丑也过不去就是了。

#include 
#include 
#include 
#include 
#include 
using namespace std;
struct rec{
    int id, col;
}arr[100010];
struct que{
    int x, y, l, r, lca, a, b, id; long long ans;
};
int T, n, m, to[100010];
inline int rd(){
    int a=0; char c=getchar();
    while(!isdigit(c)) c=getchar();
    while(isdigit(c)) (a*=10)+=c-'0', c=getchar();
    return a;
}
// 离散化
void lis(){
    sort(arr+1, arr+n+1, [](rec a, rec b){return a.colint t=1;
    for(int i=1;i<=n;){
        int p=arr[i].col; to[t]=p;
        while(i<=n&&arr[i].col==p) arr[i++].col=t;
        t++;
    }
    sort(arr+1, arr+n+1, [](rec a, rec b){return a.idlong long gcd(long long a, long long b){
    if(!a) return b;
    while(b)
        a%=b, swap(a, b);
    return a;
}
// 莫队
namespace mo{
    que qs[100010];
    int seq[200010], op[100010], ed[100010], ed2[100010], T, qpt, bk, bel[200010];
    int cnt[100010], cnt2[100010]; long long sum[100010], sum2[100010];
    bool ext[100010], u[200010];
    void init(){
        T=qpt=0;
        memset(cnt, 0, sizeof cnt); memset(sum, 0, sizeof sum);
        memset(cnt2, 0, sizeof cnt2); memset(sum2, 0, sizeof sum2);
        memset(ext, 0, sizeof ext); memset(u, 0, sizeof u);
    }
    // 处理询问
    void prework(){
        bk=ceil(sqrt(T));
        for(int i=0, t=0;ifor(int j=0;i+jfor(int i=0;iif(qs[i].lca){
                if(qs[i].x==qs[i].y){
                    if(qs[i].a==1||qs[i].b==1) qs[i].ans=to[arr[qs[i].x].col];
                    else qs[i].ans=0;
                    continue;
                }
                if(op[qs[i].x]>op[qs[i].y]) swap(qs[i].x, qs[i].y);
                if(qs[i].x==qs[i].lca) qs[i].l=op[qs[i].x]+1;
                else qs[i].l=ed[qs[i].x];
                qs[i].r=op[qs[i].y];
            }
            else
                qs[i].l=op[qs[i].x], qs[i].r=ed[qs[i].x];
        }
    }
    void inc(int ss){
        if(!u[ss]) return; int p=seq[ss];
        sum2[cnt2[arr[p].col]++]-=to[arr[p].col];
        sum2[cnt2[arr[p].col]]+=to[arr[p].col];
    }
    void dec(int ss){
        if(!u[ss]) return; int p=seq[ss];
        sum2[cnt2[arr[p].col]--]-=to[arr[p].col];
        sum2[cnt2[arr[p].col]]+=to[arr[p].col];
    }
    void tog(int p){
        if(ext[p]) sum[cnt[arr[p].col]--]-=to[arr[p].col], sum[cnt[arr[p].col]]+=to[arr[p].col];
        else sum[cnt[arr[p].col]++]-=to[arr[p].col], sum[cnt[arr[p].col]]+=to[arr[p].col];
        ext[p]^=1;
    }
    void go(){
        prework();
        sort(qs, qs+qpt, [](que a, que b){return bel[a.l]==bel[b.l]?a.rint l=0, r=0; ext[1]=1; sum[1]=sum2[1]=to[arr[1].col]; cnt[arr[1].col]=cnt2[arr[1].col]=1;
        for(int i=0;iwhile(lwhile(l>qs[i].l) tog(seq[--l]), inc(l);
            while(rwhile(r>qs[i].r) tog(seq[r]), dec(r--);
            if(qs[i].lca){
                if(qs[i].x==qs[i].y) continue;
                tog(qs[i].lca); qs[i].ans=gcd(sum[qs[i].a], sum[qs[i].b]);
                tog(qs[i].lca);
            }
            else
                qs[i].ans=gcd(sum2[qs[i].a], sum2[qs[i].b]);
        }
        sort(qs, qs+qpt, [](que a, que b){return a.idnamespace tree{
    struct edge{
        int to;
        edge *next;
        edge(int t, edge *n):to(t), next(n){}
        edge(){}
    }pool[200010], *g[100010];
    int T, fa[100010], son[100010], siz[100010], top[100010], dep[100010];
    void init(){
        T=0; memset(son, 0, sizeof son);
        memset(g, 0, sizeof g);
    }
    void addedge(int u, int v){
        g[u]=&(pool[T++]=edge(v, g[u]));
        g[v]=&(pool[T++]=edge(u, g[v]));
    }
    void dfs(int p){
        siz[p]=1; mo::u[mo::T]=1; mo::seq[mo::op[p]=mo::T++]=p;
        for(edge *t=g[p];t;t=t->next){
            if(t->to==fa[p]) continue;
            fa[t->to]=p; dep[t->to]=dep[p]+1;
            dfs(t->to);
            siz[p]+=siz[t->to];
            if(siz[t->to]>siz[son[p]]) son[p]=t->to;
        }
        mo::seq[mo::ed[p]=mo::T++]=p;
    }
    void dfs2(int p, int t){
        top[p]=t;
        if(son[p]) dfs2(son[p], t);
        for(edge *t=g[p];t;t=t->next){
            if(t->to==fa[p]||t->to==son[p]) continue;
            dfs2(t->to, t->to);
        }
    }
    int lca(int u, int v){
        while(top[u]!=top[v]){
            if(dep[top[u]]else u=fa[top[u]];
        }
        return dep[u]// 处理询问
void rd(que &a){
    a.lca=rd(); a.x=rd(), a.y=rd(); a.a=rd(), a.b=rd();
    if(a.lca==1) a.lca=0;
    else a.lca=tree::lca(a.x, a.y);
}
int main(){
    T=rd();
    for(int r=1;r<=T;r++){
        printf("Case #%d:\n", r);
        tree::init(); mo::init();
        n=rd(), m=rd();
        for(int i=1;i<=n;i++) arr[i].id=i, arr[i].col=rd();
        lis();
        for(int i=1;i1); tree::dfs2(1, 1);
        for(int i=0;ifor(int i=0;iprintf("%lld\n", mo::qs[i].ans);
    }
    return 0;
}

希望多遇到良心出题人:)
不过也是自己菜。

你可能感兴趣的:(多校,莫队)