Cerinta completa

Taylor loves trees, and this new challenge has him stumped!

Consider a tree, , consisting of nodes. Each node is numbered from to , and each node has an integer, , attached to it.

A query on tree takes the form w x y z. To process a query, you must print the count of ordered pairs of integers such that the following four conditions are all satisfied:

  • the path from node to node .
  • path from node to node .

Given and queries, process each query in order, printing the pair count for each query on a new line.

Input Format

The first line contains two space-separated integers describing the respective values of (the number of nodes) and (the number of queries).
The second line contains space-separated integers describing the respective values of each node (i.e., ).
Each of the subsequent lines contains two space-separated integers, and , defining a bidirectional edge between nodes and .
Each of the subsequent lines contains a w x y z query, defined above.

Constraints

Scoring for this problem is Binary, that means you have to pass all the test cases to get a positive score.

Output Format

For each query, print the count of ordered pairs of integers satisfying the four given conditions on a new line.

Sample Input

10 5
10 2 3 5 10 5 3 6 2 1
1 2
1 3
3 4
3 5
3 6
4 7
5 8
7 9
2 10
8 5 2 10
3 8 4 9
1 9 5 9
4 6 4 6
5 8 5 8

Sample Output

0
1
3
2
0

Explanation

We perform queries on the following tree:

image

  1. Find the number of valid ordered pairs where is in the path from node to node and is in the path from node to node . No such pair exists, so we print .
  2. Find the number of valid ordered pairs where is in the path from node to node and is in the path from node to node . One such pair, , exists, so we print .
  3. Find the number of valid ordered pairs where is in the path from node to node and is in the path from node to node . Three such pairs, , , and exist, so we print .
  4. Find the number of valid ordered pairs where is in the path from node to node and is in the path from node to node . Two such pairs, and , exist, so we print .
  5. Find the number of valid ordered pairs where is in the path from node to node and is in the path from node to node . No such pair exists, so we print .

Limbajul de programare folosit: cpp14

Cod:

#include <cstdlib>
#include <cstdio>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#include <cstring>
#include <cassert>

using namespace std;

typedef long long LL;
typedef unsigned long long ULL;

#define SIZE(x) (int((x).size()))
#define rep(i,l,r) for (int i=(l); i<=(r); i++)
#define repd(i,r,l) for (int i=(r); i>=(l); i--)
#define rept(i,c) for (__typeof((c).begin()) i=(c).begin(); i!=(c).end(); i++)

#ifndef ONLINE_JUDGE
#define debug(x) { cerr<<#x<<" = "<<(x)<<endl; }
#else
#define debug(x) {}
#endif

#define maxn 100010
#define LIM 100

int ta[maxn];

void ta_modify(int x, int y)
{
    while (x<maxn) ta[x]+=y, x+=x&-x;
}

int ta_query(int x)
{
    int ret=0;
    while (x) ret+=ta[x], x-=x&-x;
    return ret;
}

void ds_modify(int l, int r, int c)
{
    ta_modify(l,c);
    ta_modify(r+1,-c);
}

int ds_query(int v)
{
    return ta_query(v);
}

int dfsN;
int dfsLeft[maxn], dfsRight[maxn];
int lg2[maxn], p[maxn][17], depth[maxn];
vector<int> e[maxn];

void dfs(int cur, int pre, int dep)
{
    dfsN++; dfsLeft[cur]=dfsN;
    depth[cur]=dep;
    p[cur][0]=pre;
    rep(i,1,lg2[dep]) p[cur][i]=p[p[cur][i-1]][i-1];
    rept(it,e[cur]) if (*it!=pre) dfs(*it,cur,dep+1);
    dfsRight[cur]=dfsN;
}

int movedep(int x, int y)
{
    if (y<0) return 0;
    while (y) x=p[x][lg2[y&-y]], y-=y&-y;
    return x;
}

int lca(int x, int y)
{
    if (depth[x]<depth[y]) swap(x,y);
    x=movedep(x,depth[x]-depth[y]);
    repd(i,16,0)
        if (p[x][i]!=p[y][i])
        {
            x=p[x][i]; y=p[y][i];
        }
    if (x==y) return x;
    return p[x][0];
}

int get_dist(int x, int y)
{
    int z=lca(x,y);
    return depth[x]+depth[y]-2*depth[z]+1;
}

int all, ti[5][2];

void check_intersect(int p1, int p2, int q1, int q2)
{
    if (depth[p2]>depth[q2])
    {
        swap(p1,q1); swap(p2,q2);
    }
    if (depth[p1]<depth[q2]) return;
    if (lca(p1,q2)!=q2 || lca(q2,p2)!=p2) return;
    int z=lca(p1,q1);
    rep(i,1,all) if (ti[i][0]==z && ti[i][1]==q2) return;
    rep(i,1,all) if (ti[i][1]==z && ti[i][0]==q2) return;
    //if (z==q2) rep(i,1,all) if (ti[i][0]==z || ti[i][1]==z) return;
    all++; ti[all][0]=z; ti[all][1]=q2;
}

struct tasktype
{
    int x, y, c;
    tasktype() {}
    tasktype(int x, int y, int c): x(x), y(y), c(c) {}
};

vector<tasktype> eventAddList[maxn], eventQueryList[maxn];

void addQueryEvent(int i, int p1, int q1, int c)
{
    p1=dfsLeft[p1]; q1=dfsLeft[q1];
    eventQueryList[p1].push_back(tasktype(q1,i,c));
}

void addContributionEvent(int p1, int p2, int q1, int q2)
{
    eventAddList[p1].push_back(tasktype(q1,q2,1));
    eventAddList[p2+1].push_back(tasktype(q1,q2,-1));
}

void add_task(int i, int p1, int p2, int q1, int q2)
{
    if (!p1 || !p2 || !q1 || !q2) return;
    addQueryEvent(i,p1,q1,1);
    if (p[q2][0]) addQueryEvent(i,p1,p[q2][0],-1);
    if (p[p2][0]) addQueryEvent(i,p[p2][0],q1,-1);
    if (p[p2][0] && p[q2][0]) addQueryEvent(i,p[p2][0],p[q2][0],1);
}

map<int, vector<int> > clist;
int color[maxn];
int q[maxn][6];
int ans[maxn];

void lemon()
{
    lg2[1]=0; rep(i,2,maxn-1) lg2[i]=lg2[i>>1]+1;
    int n,qa; scanf("%d%d",&n,&qa);
    rep(i,1,n) 
    {
        scanf("%d",&color[i]);
        clist[color[i]].push_back(i);
    }
    rep(i,1,n-1)
    {
        int x,y; scanf("%d%d",&x,&y);
        e[x].push_back(y);
        e[y].push_back(x);
    }
    rep(i,1,qa)
    {
        scanf("%d%d%d%d",&q[i][0],&q[i][1],&q[i][2],&q[i][3]);
    }
    dfsN=0;
    dfs(1,0,0);
    rep(i,1,qa) ans[i]=0;
    rep(i,1,qa)
    {
        all=0;
        int z1=lca(q[i][0],q[i][1]);
        int z2=lca(q[i][2],q[i][3]);
        
        q[i][4]=z1; q[i][5]=z2;
        
        check_intersect(q[i][0],z1,q[i][2],z2);
        check_intersect(q[i][0],z1,q[i][3],z2);
        check_intersect(q[i][1],z1,q[i][2],z2);
        check_intersect(q[i][1],z1,q[i][3],z2);
        
        int t1=movedep(q[i][1],depth[q[i][1]]-depth[z1]-1);
        int t2=movedep(q[i][3],depth[q[i][3]]-depth[z2]-1);
        
        add_task(i,q[i][0],z1,q[i][2],z2);
        add_task(i,q[i][0],z1,q[i][3],t2);
        add_task(i,q[i][1],t1,q[i][2],z2);
        add_task(i,q[i][1],t1,q[i][3],t2);
        
        if (all>0)
        {
            rep(k,1,all)
                ans[i]-=get_dist(ti[k][0],ti[k][1]);
                
            ans[i]+=all-1;
        }
    }
    
    rept(it,clist)
    {
        int cl=it->first;
        if (it->second.size()<=LIM)
        {
            int s=it->second.size();
            rep(i,0,s-1)
                rep(j,0,s-1)
                {
                    int i1=it->second[i], j1=it->second[j];
                    addContributionEvent(dfsLeft[i1], dfsRight[i1], dfsLeft[j1], dfsRight[j1]);
                }
        }
        else
        {
            rept(it2,it->second)
                ds_modify(dfsLeft[*it2],dfsRight[*it2],1);
                
            rep(i,1,qa)
            {
                int x1=ds_query(dfsLeft[q[i][0]])+ds_query(dfsLeft[q[i][1]])-2*ds_query(dfsLeft[q[i][4]]);
                if (color[q[i][4]]==cl) x1++;
                //printf("%d: %d %d %dn",cl,q[i][0],q[i][1],x1);
                int x2=ds_query(dfsLeft[q[i][2]])+ds_query(dfsLeft[q[i][3]])-2*ds_query(dfsLeft[q[i][5]]);
                if (color[q[i][5]]==cl) x2++;
                //printf("%d: %d %d %dn",cl,q[i][2],q[i][3],x2);
                ans[i]+=x1*x2;
            }
            
            rept(it2,it->second)
                ds_modify(dfsLeft[*it2],dfsRight[*it2],-1);
            
        }
    }
    
    rep(i,1,n)
    {
        rept(it,eventAddList[i]) ds_modify(it->x,it->y,it->c);
        rept(it,eventQueryList[i]) ans[it->y]+=it->c*ds_query(it->x);
    }
    
    rep(i,1,qa) printf("%d\n",ans[i]);
}

int main()
{
    ios::sync_with_stdio(true);
    #ifndef ONLINE_JUDGE
        //freopen("8.in","r",stdin);
    #endif
    lemon();
    return 0;
}

Scor obtinut: 1.0

Submission ID: 464653406

Link challenge: https://www.hackerrank.com/challenges/counting-on-a-tree/problem

Counting On a Tree