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

来源:互联网 发布:php 去除数组重复值 编辑:程序博客网 时间:2024/05/29 19:14

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);            }        }    }}









原创粉丝点击