玲珑学院OJ 1132 Down the Rabbit Hole【Dfs序+暴力】

75 篇文章 0 订阅

1132 - Down the Rabbit Hole

Time Limit:1s Memory Limit:512MByte

Submissions:135Solved:54

DESCRIPTION

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 51 2 3 4 51 21 33 43 52 4 52 1 52 3 51 5 12 4 5
SAMPLE OUTPUT
1003
HINT
n,m <= 100000 , a[i] <= 1000000000!!!!注意,这个树是个红黑树哦,红黑树有特殊的性质哦!!!!!!!!红黑树的树高是多少大家仔细回想一下!!!!!!!!!!!!!!!!!!!!红黑树树高是O( logn )的!!!!!!!!!!若出现爆栈问题,改栈方法请参考1093题目代码1093地址:http://www.ifrog.cc/acm/problem/1093代码地址:http://ideone.com/Wk24ET

思路:


已经提示红黑树的树高是O(logn),那么树高最多也就是20左右。那么如果我们能够找到查询的两点间的路径,那么直接暴力求一下逆序数即可。


先O(n)预处理出来一个Dfs序,那么我们对于查询的两个点u,v,我们从节点1作为根向下根据Dfs序的相关信息,不断的向u的祖先节点走去,直到走到节点u。对于节点v同理,我们从节点1作为根向下根据Dfs序,不断的向v的虚线节点走去,直到走到节点v.


那么我们现在有两条路径,一条是从1到u,另外一条是从1到v.

那么两个路径最后一个重复的位子,就是两个点的LCA.然后将两个序列拼接在一起然后暴力求一下逆序数即可。


Ac代码:

#include<stdio.h>
#include<string.h>
#include<vector>
using namespace std;
int a[150000];
vector<int >mp[150000];
int cnt,n,m,len1,len2;
int L[150000],R[150000];
int b[100];
int c[100];
int d[100];
void Dfs(int u,int from)
{
    L[u]=++cnt;
    for(int i=0;i<mp[u].size();i++)
    {
        int v=mp[u][i];
        if(v==from)continue;
        Dfs(v,u);
    }
    R[u]=cnt;
}
void Dfs1(int u,int from,int target)
{
    b[len1++]=u;
    if(u==target)return ;
    for(int i=0;i<mp[u].size();i++)
    {
        int v=mp[u][i];
        if(v==from)continue;
        if(L[v]<=L[target]&&L[target]<=R[v])
        {
            Dfs1(v,u,target);
        }
    }
}
void Dfs2(int u,int from,int target)
{
    c[len2++]=u;
    if(u==target)return ;
    for(int i=0;i<mp[u].size();i++)
    {
        int v=mp[u][i];
        if(v==from)continue;
        if(L[v]<=L[target]&&L[target]<=R[v])
        {
            Dfs2(v,u,target);
        }
    }
}
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        cnt=0;
        for(int i=1;i<=n;i++)mp[i].clear();
        memset(a,0,sizeof(a));
        for(int i=1;i<=n;i++)scanf("%d",&a[i]);
        for(int i=1;i<=n-1;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            mp[x].push_back(y);
            mp[y].push_back(x);
        }
        Dfs(1,-1);
        for(int i=0;i<m;i++)
        {
            int op,x,y;
            scanf("%d%d%d",&op,&x,&y);
            if(op==1)
            {
                a[x]=y;
            }
            else
            {
                len1=0;
                len2=0;
                memset(b,0,sizeof(b));
                memset(c,0,sizeof(c));
                Dfs1(1,-1,x);
                Dfs2(1,-1,y);
                /*
                for(int j=0;j<len1;j++)printf("%d ",b[j]);
                printf("\n");
                for(int j=0;j<len2;j++)printf("%d ",c[j]);
                printf("\n");*/
                int pos=-1;
                for(int j=0;j<len1;j++)
                {
                    if(b[j]==c[j])continue;
                    else
                    {
                        pos=j-1;
                        break;
                    }
                }
                if(pos==-1)pos=min(len1-1,len2-1);
                int tmp=0;
                for(int j=len1-1;j>=pos;j--)
                {
                    d[tmp++]=b[j];
                }
                for(int j=pos+1;j<len2;j++)
                {
                    d[tmp++]=c[j];
                }
                int output=0;
                for(int j=0;j<tmp;j++)
                {
                    for(int k=0;k<j;k++)
                    {
                        if(a[d[k]]>a[d[j]])output++;
                    }
                }
                printf("%d\n",output);
            }
        }
    }
}









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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值