• Codeforces Round #263 (Div. 1)


    B 树形dp

    组合的思想。

    Z队长的思路。

    dp[i][1]表示以i为跟结点的子树向上贡献1个的方案,dp[i][0]表示以i为跟结点的子树向上贡献0个的方案.

    如果当前为叶子节点,dp[i][0] = 1,(颜色为1,可以断开与父节点的连接,颜色为0,不断开,方案恒为1),dp[i][1] = co[i](i节点的颜色)。

    非叶子节点:将所有孩子节点的dp[child][0]乘起来为sum,孩子贡献为0的总方案。

    当前颜色为0时, dp[i][1] += sum/dp[child][0]*dp[child][1],(选当前孩子贡献的1) ,

    dp[i][0] = sum+dp[i][1](将i与其父亲断开)。

    当颜色为1时,  dp[i][1] (需儿子们贡献为0)= dp[i][0](需与父亲断开) = sum.

    中间除法取模需要用到逆元。 (s/y)%mod = (s*y^mod-2)%mod;

     1 #include <iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<stdlib.h>
     6 #include<vector>
     7 #include<cmath>
     8 #include<queue>
     9 #include<set>
    10 using namespace std;
    11 #define N 100010
    12 #define LL long long
    13 #define INF 0xfffffff
    14 #define mod 1000000007
    15 const double eps = 1e-8;
    16 const double pi = acos(-1.0);
    17 const double inf = ~0u>>2;
    18 vector<int>ch[N];
    19 int dp[N][2];
    20 int co[N];
    21 LL q_mod(LL a,LL b)
    22 {
    23     LL d,t;
    24     d = 1,t=a;
    25     while(b)
    26     {
    27         if(b&1) d = (d*t)%mod;
    28         b/=2;
    29         t = (t*t)%mod;
    30     }
    31     return d;
    32 }
    33 LL cal(LL s,LL y,LL x)
    34 {
    35     s = (s*x)%mod;
    36     return (s*q_mod(y,mod-2))%mod;
    37 }
    38 void dfs(int u,int pre)
    39 {
    40     int i;
    41     LL s0=1;
    42     int flag = 0;
    43     for(i = 0 ; i < ch[u].size() ;i++)
    44     {
    45         int v = ch[u][i];
    46         if(v==pre) continue;
    47         flag = 1;
    48         dfs(v,u);
    49         s0 = (s0*dp[v][0])%mod;
    50     }
    51     if(!flag)
    52     {
    53         dp[u][0] = 1;
    54         dp[u][1] = co[u];
    55         return ;
    56     }
    57     if(co[u]==0)
    58     {
    59         dp[u][0] = s0;
    60         dp[u][1] = 0;
    61         for(i = 0 ;i < ch[u].size() ; i++)
    62         {
    63             int v = ch[u][i];
    64             if(v==pre) continue;
    65             if(!dp[v][1]) continue;
    66             dp[u][1] = (dp[u][1]+cal(s0,dp[v][0],dp[v][1]))%mod;
    67         }
    68         dp[u][0] = (dp[u][0]+dp[u][1])%mod;
    69     }
    70     else
    71     {
    72         dp[u][0] = s0;
    73         dp[u][1] = s0;
    74     }
    75 }
    76 int main()
    77 {
    78     int n,i;
    79     cin>>n;
    80     for(i = 0 ; i < n-1; i++)
    81     {
    82         int u;
    83         scanf("%d",&u);
    84         ch[u].push_back(i+1);
    85         ch[i+1].push_back(u);
    86     }
    87     for(i = 0 ; i < n; i++)
    88     scanf("%d",&co[i]);
    89     dfs(0,-1);
    90     cout<<dp[0][1]<<endl;
    91     return 0;
    92 }
    View Code

    C 标记数组开始和尾部 线段树维护。

    因为有翻转操作,当前数组的开始与结尾不确定,用两个变量标记。

    线段树节点表示以它为右端点的线段   比如 0-1-2-3-4-5-6  分别用1 2 3 4 5 6表示它左边那条线段。

    如果旋转位置大于当前线段长度的一半,先把此线段翻转,再翻转相对的较短一段。

      1 #include <iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 #include<stdlib.h>
      6 #include<vector>
      7 #include<cmath>
      8 #include<queue>
      9 #include<set>
     10 using namespace std;
     11 #define N 100000
     12 #define LL long long
     13 #define INF 0xfffffff
     14 const double eps = 1e-8;
     15 const double pi = acos(-1.0);
     16 const double inf = ~0u>>2;
     17 int s[N<<2];
     18 int a[N];
     19 void up(int w)
     20 {
     21     s[w] = s[w<<1]+s[w<<1|1];
     22 }
     23 void build(int l,int r,int w)
     24 {
     25     if(l==r)
     26     {
     27         s[w] = a[l] = 1;
     28         return ;
     29     }
     30     int m = (l+r)>>1;
     31     build(l,m,w<<1);
     32     build(m+1,r,w<<1|1);
     33     up(w);
     34 }
     35 void update(int p,int d,int l,int r,int w)
     36 {
     37     if(l==r)
     38     {
     39         s[w]+=d;
     40         a[l] = s[w];
     41         return ;
     42     }
     43     int m = (l+r)>>1;
     44     if(p<=m) update(p,d,l,m,w<<1);
     45     else update(p,d,m+1,r,w<<1|1);
     46     up(w);
     47 }
     48 int query(int a,int b,int l,int r,int w)
     49 {
     50     if(a<=l&&b>=r)
     51     {
     52         return s[w];
     53     }
     54     int m = (l+r)>>1;
     55     int res = 0;
     56     if(a<=m) res+=query(a,b,l,m,w<<1);
     57     if(b>m) res+=query(a,b,m+1,r,w<<1|1);
     58     return res;
     59 }
     60 int main()
     61 {
     62     int n,m,i,j;
     63     cin>>n>>m;
     64     build(1,n,1);
     65     int lef=1,rig=n;
     66     while(m--)
     67     {
     68         int x,y,z;
     69         scanf("%d%d",&x,&y);
     70         if(x==1)
     71         {
     72             int mid = (abs(rig-lef)+1)>>1;
     73             //cout<<mid<<" .."<<rig<<" "<<lef<<endl;
     74             if(y>mid)
     75             {
     76                 swap(lef,rig);
     77                 y = abs(rig-lef)+1-y;
     78             }
     79             //cout<<y<<".."<<endl;
     80             int st,en;
     81             if(lef<rig)
     82             {
     83                 st = lef+y-1;
     84                 j = st+1;
     85                 for(i = st ; i >= lef ; i--)
     86                 {
     87                     update(j,a[i],1,n,1);
     88                     j++;
     89                 }
     90                 lef = st+1;
     91             }
     92             else
     93             {
     94                 st = lef-y+1;
     95                 j = st-1;
     96                 for(i = st ;i <= lef ;i++)
     97                 {
     98                     update(j,a[i],1,n,1);
     99                     j--;
    100                 }
    101                 lef = st-1;
    102             }
    103         }
    104         else
    105         {
    106             scanf("%d",&z);
    107             y++;
    108             int ll,rr;
    109             if(lef>rig)
    110             {
    111                 ll = lef-z+1;
    112                 rr = lef-y+1;
    113             }
    114             else
    115             {
    116                 ll = lef+y-1;
    117                 rr = lef+z-1;
    118             }
    119             cout<<query(ll,rr,1,n,1)<<endl;
    120         }
    121     }
    122     return 0;
    123 }
    View Code
  • 相关阅读:
    开发笔记-图片拉伸保持不变形
    开发笔记-简单渐变动画的实现
    开发笔记- iOS监听某些事件的方法简单梳理
    开发笔记-UIApplication代理
    开发笔记-UIApplication单例
    常见的UNIX命令
    知识点回顾-简单的TableView单组数据展示/多组数据展示
    开发技巧-改变按钮属性3部曲
    字典--plist
    如何使用JS实现页面内容随机显示
  • 原文地址:https://www.cnblogs.com/shangyu/p/3940015.html
Copyright © 2020-2023  润新知