玲珑OJ Down the Rabbit Hole (DFS序查找路径)

5.632
我(或者是在读这篇文字的你)不属于这个世界
这是世界的界限
6.41
世界的意义必定存在于世界之外
世界中的一切事物如其所存在般而存在,如其所发生般而发生
世界之中不存在价值

果然……好女人要有的是,烟、楼顶……还有轻飘飘的衣服呀……

某天,水上由岐看见天上掉下的毛绒玩具。
“被天空接受”那是为了寻找不知何时开始在这个城市流传的“回归天空之路”的行为。

为了被天空接受而被扔出去的木偶,在空中飞舞并最终坠落。
那是为了将其本身即为世界的少女送予天空的少女的行为。
横跨天河的vega与Altair,被称为织女星与牛郎星的两颗星星,再加上北十字星的顶之星deneb,被称为夏季大三角。 那是形容三位一体的圣之图形。
只有夏季大三角在天空闪耀之时,世界才与天空相遇。

我想试一试,第一次,也是最后一次的恶作剧

您正在打galgame,然后突然发现您今天太颓了,于是想写个数据结构题练练手:
说到数据结构,当然要说红黑树啦
有一个红黑树,n个点,然而由于写丑了,所以里面的点权是乱的
红黑树点权当然不能是乱的啊,所以这只是一道题而已,没有让您写红黑树,不用担心
m个操作:
1.询问一条链x -> y中的逆序对对数
2.修改x点的点权为y
所谓逆序对就是说在一个序列中,i < j , a[i] > a[j] 则( i , j )为一个逆序对
1操作可以理解为把x -> y这条链当作一个序列,求这个序列的逆序对对数

!!!!注意,这个树是个红黑树哦,红黑树有特殊的性质哦!!!! !!!!红黑树的树高是多少大家仔细回想一下!!!!!!!!!! !!!!!!!!!!红黑树树高是O( logn )的!!!!!!!!!!
INPUT
第一行两个数n,m 第二行n个数,表示每个节点的点权ai 之后n-1行,每行两个点x,y表示x点和y点之间连有一条边 之后m行,每行为opt x y 如果opt为1,表示江x节点的值修改为y 如果opt为2,表示求x -> y这条链上的逆序对对数 答案对19260817取膜
OUTPUT
对于每个询问,输出一个数表示答案
SAMPLE INPUT
5 5 1 2 3 4 5 1 2 1 3 3 4 3 5 2 4 5 2 1 5 2 3 5 1 5 1 2 4 5
SAMPLE OUTPUT
1 0 0 3
HINT
 
题解:
这棵树是红黑树,所以树高只有 log(n) ,所以可以求出序列之后暴力!
这题最巧妙的地方在于利用DFS序进行剪枝,使找路径的时间大大优化了.
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <bits/stdc++.h>
#define DEBUG 0
using namespace std;
const int N = 150000;
vector<int>edge[N];

int in[N],out[N];
int val[N];
int n,m,num;
int B[100],C[100],D[100];
void dfs1(int u,int fa)
{
    num++;
    in[u] = num;
    for(int i=0; i<edge[u].size(); i++)
    {
        int v = edge[u][i];
        if(v==fa) continue;
        dfs1(v,u);
    }
    out[u] = num;
}
void dfs2(int u,int fa,int target,int B[],int *len)
{
    B[(*len)++] = u;
    if(u==target) return;
    for(int i=0; i<edge[u].size(); i++)
    {
        int v = edge[u][i];
        if(v==fa) continue;
        if(in[v]<=in[target]&&in[target]<=out[v])
            dfs2(v,u,target,B,len);
    }
}

void init(int n)
{
    for(int i=1; i<=n; i++) edge[i].clear();
    num = 0;
}


int main()
{

    while(scanf("%d%d",&n,&m)!=EOF)
    {
        init(n);
        for(int i=1; i<=n; i++) scanf("%d",&val[i]);
        for(int i=1; i<n; i++)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            edge[u].push_back(v);
            edge[v].push_back(u);
        }
        dfs1(1,-1);
        int op,x,y;
        while(m--)
        {
            scanf("%d%d%d",&op,&x,&y);
            if(op==1)
            {
                val[x] = y;
                continue;
            }
            int len1 = 0,len2 = 0;
            int lca = -1;
            dfs2(1,-1,x,B,&len1);
            dfs2(1,-1,y,C,&len2);
            for(int i=0; i<min(len1,len2); i++)
            {
                if(B[i]==C[i]) continue;
                lca = i-1;
                break;
            }
            if(lca==-1) lca = min(len1-1,len2-1);
            int k = 0;
            for(int i=len1-1; i>=lca; i--) D[k++] = B[i];
            for(int i=lca+1; i<len2; i++) D[k++] = C[i];
            int ans = 0;
            for(int i=0; i<k; i++)
            {
                for(int j=0; j<i; j++)
                {
                    if(val[D[i]]<val[D[j]]) ans = (ans+1)%19260817;
                }
            }
            printf("%d\n",ans);
        }
    }
    return 0;
}

 

Down the Rabbit Hole

posted @ 2017-08-30 10:59  樱花庄的龙之介大人  阅读(31)  评论(0编辑  收藏