zoukankan      html  css  js  c++  java
  • bzoj 3772 :精神污染 线段树+打标记 or 主席树

    3772: 精神污染

    Time Limit: 10 Sec  Memory Limit: 64 MB
    Submit: 315  Solved: 87
    [Submit][Status][Discuss]

    Description

    兵库县位于日本列岛的中央位置,北临日本海,南面濑户内海直通太平洋,中央部位是森林和山地,与拥有关西机场的大阪府比邻而居,是关西地区面积最大的县,是集经济和文化于一体的一大地区,是日本西部门户,海陆空交通设施发达。濑户内海沿岸气候温暖,多晴天,有日本少见的贸易良港神户港所在的神户市和曾是豪族城邑“城下町”的姬路市等大城市,还有以疗养地而闻名的六甲山地等。
    兵库县官方也大力发展旅游,为了方便,他们在县内的N个旅游景点上建立了n-1条观光道,构成了一棵图论中的树。同时他们推出了M条观光线路,每条线路由两个节点x和y指定,经过的旅游景点就是树上x到y的唯一路径上的点。保证一条路径只出现一次。
    你和你的朋友打算前往兵库县旅游,但旅行社还没有告知你们最终选择的观光线路是哪一条(假设是线路A)。这时候你得到了一个消息:在兵库北有一群丧心病狂的香菜蜜,他们已经选定了一条观光线路(假设是线路B),对这条路线上的所有景点都释放了【精神污染】。这个计划还有可能影响其他的线路,比如有四个景点1-2-3-4,而【精神污染】的路径是1-4,那么1-3,2-4,1-2等路径也被视为被完全污染了。
    现在你想知道的是,假设随便选择两条不同的路径A和B,存在一条路径使得如果这条路径被污染,另一条路径也被污染的概率。换句话说,一条路径被另一条路径包含的概率。

    Input

    第一行两个整数N,M
    接下来N-1行,每行两个数a,b,表示A和B之间有一条观光道。
    接下来M行,每行两个数x,y,表示一条旅游线路。

    Output

    所求的概率,以最简分数形式输出。
     
    答案很容易就可以看出来是 Σ(1<=i<=m)包含第i条路径的路径数/c(m,2)。
    那我们考虑每一条路径被多少条路径包含。
    一条路径A->B有三种情况,一是A和B分属LCA的两颗子树里,二是A或B是LCA,三是A=B.
    对于第一种情况我们查A的子树中有多少询问一端在A的子树中,一端在B的子树中。
    我们可以类似noip2016 day1t2的思路在每个询问的两个端点打上标记,在A点存上B,在B点存上A,统计答案时我们就只在A点查。
    动态维护一颗线段树,树的下标为dfs序,按当前遍历到的所有标记所指向节点的dfs序存进去,统计区间。
    当我们dfs到A点时,对于A的每一个询问,先把答案减去线段树中[st[B],ed[B]]]这个区间的和,然后把A点的标记放进树里,dfs子树,再把答案加上[st[B],ed[B]]]这个区间的和。
    相当于去除了子树之外的影响。
    第二种情况差不多,只不过询问区间不一样。
    第三种需要特判,不多说了。
    记得把初始答案设为-m,因为这样计算会认为自己包含自己。
     
      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 #include<vector>
      6 #define LL long long
      7 #define ls x*2,l,mid
      8 #define    rs x*2+1,mid+1,r 
      9 #define N 200005
     10 using namespace std;
     11 LL gcd(LL a,LL b)
     12 {
     13     if(!b)return a;
     14     return gcd(b,a%b);
     15 }
     16 int n,m;
     17 int head[N],ver[N*2],nxt[N*2],tot;
     18 void add(int a,int b)
     19 {
     20     tot++;nxt[tot]=head[a];head[a]=tot;ver[tot]=b;return ;
     21 }
     22 int dep[N],fa[N][20],dfn[N],z,ed[N];
     23 void dfs(int x,int f)
     24 {
     25     dfn[x]=++z;
     26     for(int i=head[x];i;i=nxt[i])
     27     {
     28         if(ver[i]==f)continue;
     29         dep[ver[i]]=dep[x]+1;
     30         fa[ver[i]][0]=x;
     31         dfs(ver[i],x);
     32     }ed[x]=z;
     33 }
     34 void yu()
     35 {
     36     for(int i=1;i<=17;i++)
     37     {
     38         for(int j=1;j<=n;j++)
     39         {
     40             fa[j][i]=fa[fa[j][i-1]][i-1];
     41         }
     42     }return ;
     43 }
     44 int lca(int x,int y)
     45 {
     46     if(dep[x]<dep[y])swap(x,y);
     47     for(int i=17;i>=0;i--)
     48     {
     49         if(dep[fa[x][i]]>=dep[y])x=fa[x][i];
     50     }
     51     if(x==y)return x;
     52     for(int i=17;i>=0;i--)
     53     {
     54         if(fa[x][i]!=fa[y][i])
     55         {
     56             x=fa[x][i];y=fa[y][i];
     57         }
     58     }
     59     return fa[x][0];
     60 }
     61 int a[N*8];
     62 void add(int x,int l,int r,int pos,int z)
     63 {
     64     if(l==r)
     65     {
     66         a[x]+=z;
     67         return ;
     68     }
     69     int mid=(l+r)>>1;
     70     if(pos<=mid)add(ls,pos,z);
     71     else add(rs,pos,z);
     72     a[x]=a[x*2]+a[x*2+1];
     73 }
     74 int qur(int x,int l,int r,int ll,int rr)
     75 {
     76     if(ll>rr)return 0;
     77     if(ll<=l&&rr>=r)
     78     {
     79         return a[x];
     80     }
     81     int mid=(l+r)>>1;
     82     if(ll>mid)return qur(rs,ll,rr);
     83     if(rr<=mid)return qur(ls,ll,rr);
     84     return qur(rs,ll,rr)+qur(ls,ll,rr);
     85 }
     86 struct qr
     87 {
     88     int x,y;
     89 }q[N];
     90 struct node
     91 {
     92     int op,y;
     93     node(int xx,int yy)
     94     {
     95         op=xx;y=yy;
     96     }
     97 };
     98 int faa(int x,int y)
     99 {
    100     for(int i=17;i>=0;i--)
    101     {
    102         if(dep[fa[x][i]]>dep[y])x=fa[x][i];
    103     }
    104     return x;
    105 }
    106 vector<node>lazy[N];
    107 LL ans;
    108 int sb[N];
    109 void dp(int x,int f)
    110 {
    111     for(int i=0;i<lazy[x].size();i++)
    112     {
    113         if(!lazy[x][i].op)continue;
    114         if(lazy[x][i].op==1)
    115         {
    116             ans-=qur(1,1,n,dfn[lazy[x][i].y],ed[lazy[x][i].y]);
    117         }
    118         else
    119         {
    120             int yy=lazy[x][i].y;
    121             int now=faa(x,yy);
    122             ans-=qur(1,1,n,1,dfn[now]-1)+qur(1,1,n,ed[now]+1,n);
    123             if(x==yy)
    124             {
    125                 ans-=qur(1,1,n,dfn[x],dfn[x]);
    126             }
    127         }
    128     }
    129     for(int i=0;i<lazy[x].size();i++)
    130     {
    131         add(1,1,n,dfn[lazy[x][i].y],1);
    132         if(lazy[x][i].op==1)
    133         {
    134             int uu=lca(x,lazy[x][i].y);
    135             sb[uu]++;
    136         }
    137     }
    138     for(int i=head[x];i;i=nxt[i])
    139     {
    140         if(ver[i]==f)continue;
    141         dp(ver[i],x);
    142     }
    143     for(int i=0;i<lazy[x].size();i++)
    144     {
    145         if(!lazy[x][i].op)continue;
    146         if(lazy[x][i].op==1)
    147         {
    148             ans+=qur(1,1,n,dfn[lazy[x][i].y],ed[lazy[x][i].y]);
    149         }
    150         else
    151         {
    152             int yy=lazy[x][i].y;
    153             int now=faa(x,yy);
    154             if(x==yy)
    155             {
    156                 ans+=qur(1,1,n,dfn[x],dfn[x]);
    157                 ans+=sb[x];
    158             }
    159             ans+=qur(1,1,n,1,dfn[now]-1)+qur(1,1,n,ed[now]+1,n);
    160         }
    161     }
    162 }
    163 int main()
    164 {
    165     scanf("%d%d",&n,&m);
    166     int t1,t2;
    167     for(int i=1;i<n;i++)
    168     {
    169         scanf("%d%d",&t1,&t2);
    170         add(t1,t2);add(t2,t1);
    171     }
    172     ans=-m;
    173     dep[1]=1;
    174     dfs(1,-1);
    175     yu();
    176     for(int i=1;i<=m;i++)
    177     {
    178         scanf("%d%d",&q[i].x,&q[i].y);
    179         int tmp=lca(q[i].x,q[i].y);
    180         if(tmp==q[i].x)
    181         {
    182             lazy[q[i].y].push_back(node(2,q[i].x));
    183             if(q[i].x!=q[i].y)lazy[q[i].x].push_back(node(0,q[i].y));
    184         }
    185         else if(tmp==q[i].y)
    186         {
    187             lazy[q[i].y].push_back(node(0,q[i].x));
    188             lazy[q[i].x].push_back(node(2,q[i].y));
    189         }
    190         else 
    191         {
    192             lazy[q[i].x].push_back(node(1,q[i].y));
    193             lazy[q[i].y].push_back(node(0,q[i].x));
    194         }
    195     }    
    196     dp(1,-1);
    197     LL tt=(LL)m*(m-1)/2;
    198     LL oo=gcd(tt,ans);
    199     printf("%lld/%lld
    ",ans/oo,tt/oo);
    200     return 0;
    201 }
  • 相关阅读:
    深度学习的优化算法
    基于双向的CNN的细粒度物体识别论文翻译
    LSTM公式推导
    结巴分词python脚本
    eval() python 中的
    C++编译原理
    extern,以及在linux头文件中的应用
    iostream源码
    LINUX命令
    apt-get
  • 原文地址:https://www.cnblogs.com/ezyzy/p/6411342.html
Copyright © 2011-2022 走看看