zoukankan      html  css  js  c++  java
  • 3月部分题目简要题解

    hdu5820

    官方题解:http://www.cnblogs.com/duoxiao/p/5777700.html

     1 #include<bits/stdc++.h>
     2 
     3 using namespace std;
     4 struct node{int l,r,s;} tr[500010*40];
     5 vector<int> g[50010];
     6 int pre[50010],h[50010],n,t;
     7 int build(int l,int r)
     8 {
     9     ++t; tr[t].s=0;
    10     if (l==r) return t;
    11     int m=(l+r)>>1,q=t;
    12     tr[t].l=build(l,m);
    13     tr[t].r=build(m+1,r);
    14     return q;
    15 }
    16 
    17 int ask(int i,int l,int r,int x,int y)
    18 {
    19     if (x>y) return 0;
    20     if (x<=l&&y>=r) return tr[i].s;
    21     else {
    22         int m=(l+r)>>1,s=0;
    23         if (x<=m) s+=ask(tr[i].l,l,m,x,y);
    24         if (y>m) s+=ask(tr[i].r,m+1,r,x,y);
    25         return s;
    26     }
    27 }
    28 
    29 int add(int i,int l,int r,int x)
    30 {
    31     ++t;
    32     if (l==r)
    33     {
    34         tr[t].s=tr[i].s+1;
    35         return t;
    36     }
    37     int m=(l+r)>>1,q=t;
    38     if (x<=m)
    39     {
    40         tr[q].r=tr[i].r;
    41         tr[q].l=add(tr[i].l,l,m,x);
    42     }
    43     else {
    44         tr[q].l=tr[i].l;
    45         tr[q].r=add(tr[i].r,m+1,r,x);
    46     }
    47     tr[q].s=tr[tr[q].l].s+tr[tr[q].r].s;
    48     return q;
    49 }
    50 
    51 
    52 bool check()
    53 {
    54     memset(pre,0,sizeof(pre));
    55     for (int i=1; i<=50000; i++)
    56     {
    57         h[i]=h[i-1];
    58         for (int j=0; j<g[i].size(); j++)
    59         {
    60             int l=(!j)?0:g[i][j-1];
    61             int r=(j==g[i].size()-1)?50001:g[i][j+1];
    62            // cout <<l<<" "<<r<<" "<<pre[g[i][j]]<<" "<<ask(h[i],1,50000,l+1,r-1)<<endl;
    63             if (ask(h[i],1,50000,l+1,r-1)!=ask(h[pre[g[i][j]]],1,50000,l+1,r-1)) return 0;
    64         }
    65         for (int j=0; j<g[i].size(); j++)
    66         {
    67             h[i]=add(h[i],1,50000,g[i][j]);
    68             pre[g[i][j]]=i;
    69         }
    70     }
    71     return 1;
    72 }
    73 
    74 int main()
    75 {
    76     scanf("%d",&n);
    77     t=0;
    78     h[0]=build(1,50000); int tmp=t;
    79     while (n)
    80     {
    81         t=tmp;
    82         for (int i=1; i<=n; i++)
    83         {
    84             int x,y;
    85             scanf("%d%d",&x,&y);
    86             g[x].push_back(y);
    87         }
    88         for (int i=1; i<=50000; i++)
    89         {
    90             sort(g[i].begin(),g[i].end());
    91             g[i].erase(unique(g[i].begin(),g[i].end()),g[i].end());
    92         }
    93         if (check()) puts("YES"); else puts("NO");
    94         for (int i=1; i<=50000; i++) g[i].clear();
    95         scanf("%d",&n);
    96     }
    97 }
    View Code

    hdu5788

    官方题解:http://www.cnblogs.com/duoxiao/p/5777661.html

    其实有个简单的方法求子树的[t/2]名次:直接在dfs序上建立可持久化线段树查询即可

      1 #include<bits/stdc++.h>
      2 
      3 using namespace std;
      4 typedef long long ll;
      5 struct way{int po,next;} e[100010];
      6 struct node{int s,l,r;} tr[100010*40];
      7 int p[100010],l[100010],h[100010],w[100010],cur[100010],a[100010],r[100010],len,n,tot,t;
      8 ll c[100010],ans;
      9 void add(int x,int y)
     10 {
     11     e[++len].po=y;
     12     e[len].next=p[x];
     13     p[x]=len;
     14 }
     15 
     16 int build(int l,int r)
     17 {
     18     ++t; tr[t].s=0;
     19     if (l==r) return t;
     20     int m=(l+r)>>1,q=t;
     21     tr[t].l=build(l,m);
     22     tr[t].r=build(m+1,r);
     23     return q;
     24 }
     25 
     26 int mid(int a,int b,int l,int r,int k)
     27 {
     28     if (l==r) return l;
     29     else {
     30         int m=(l+r)>>1,s=tr[tr[b].l].s-tr[tr[a].l].s;
     31         if (k<=s) return mid(tr[a].l,tr[b].l,l,m,k);
     32         else return mid(tr[a].r,tr[b].r,m+1,r,k-s);
     33     }
     34 }
     35 
     36 int add(int i,int l,int r,int x)
     37 {
     38     ++t;
     39     if (l==r)
     40     {
     41         tr[t].s=tr[i].s+1;
     42         return t;
     43     }
     44     int m=(l+r)>>1,q=t;
     45     if (x<=m)
     46     {
     47         tr[q].r=tr[i].r;
     48         tr[q].l=add(tr[i].l,l,m,x);
     49     }
     50     else {
     51         tr[q].l=tr[i].l;
     52         tr[q].r=add(tr[i].r,m+1,r,x);
     53     }
     54     tr[q].s=tr[tr[q].l].s+tr[tr[q].r].s;
     55     return q;
     56 }
     57 
     58 void dfs1(int x)
     59 {
     60     l[x]=++tot; h[tot]=add(h[tot-1],1,100000,a[x]);
     61     for (int i=p[x]; i; i=e[i].next)
     62     {
     63         int y=e[i].po;
     64         dfs1(y);
     65     }
     66     w[x]=mid(h[l[x]-1],h[tot],1,100000,(tot-l[x]+2)/2);
     67     if (l[x]==tot) cur[x]=0; else cur[x]=mid(h[l[x]-1],h[tot],1,100000,(tot-l[x]+2)/2+1)-w[x];
     68 }
     69 
     70 void work(int x,int w)
     71 {
     72     for (int i=x; i; i-=i&(-i)) c[i]+=w;
     73 }
     74 
     75 ll ask(int x)
     76 {
     77     ll s=0;
     78     for (int i=x; i<=100000; i+=i&(-i)) s+=c[i];
     79     return s;
     80 }
     81 
     82 void dfs2(int x)
     83 {
     84     ll wh=(p[x]==0)?100000-a[x]:cur[x]-w[x];
     85     ans=max(ans,ask(a[x])+wh);
     86     if (cur[x]) work(w[x],cur[x]);
     87     for (int i=p[x]; i; i=e[i].next)
     88     {
     89         int y=e[i].po;
     90         dfs2(y);
     91     }
     92     if (cur[x]) work(w[x],-cur[x]);
     93 }
     94 
     95 int main()
     96 {
     97     t=0; h[0]=build(1,100000);
     98     int tmp=t;
     99     while (scanf("%d",&n)!=EOF)
    100     {
    101         t=tmp;
    102         len=0; memset(p,0,sizeof(p));
    103         for (int i=1; i<=n; i++) scanf("%d",&a[i]);
    104         for (int i=2; i<=n; i++)
    105         {
    106             int fa;
    107             scanf("%d",&fa);
    108             add(fa,i);
    109         }
    110         tot=0; h[1]=h[0]; dfs1(1);
    111         ll s=0;
    112         for (int i=1; i<=n; i++) s+=w[i];
    113      //   for (int i=1; i<=n; i++) cout <<"*"<<w[i]<<" "<<cur[i]<<endl;
    114         memset(c,0,sizeof(c)); ans=0;
    115         dfs2(1);
    116         printf("%lld
    ",ans+s);
    117     }
    118 }
    View Code

    hdu3605

    把n按照可选择方案二进制状态压缩,建图最大流即可

      1 #include<bits/stdc++.h>
      2 
      3 using namespace std;
      4 const int inf=1e9+7;
      5 struct way{int po,flow,next;} e[2400010];
      6 int t,n,p[2010],pre[2010],numh[2010],cur[2010],h[2010],d[2010],b[2010],m,len;
      7 
      8 void add(int x,int y,int f)
      9 {
     10      e[++len].po=y;
     11      e[len].flow=f;
     12      e[len].next=p[x];
     13      p[x]=len;
     14 }
     15 void build(int x, int y, int f)
     16 {
     17      add(x,y,f);
     18      add(y,x,0);
     19 }
     20 int sap()
     21 {
     22     memset(numh,0,sizeof(numh));
     23     memset(h,0,sizeof(h));
     24     numh[0]=t+1;
     25     for (int i=0; i<=t; i++) cur[i]=p[i];
     26     int j,u=0,s=0,neck=inf;
     27     while (h[0]<t+1)
     28     {
     29           d[u]=neck;
     30           bool ch=1;
     31           for (int i=cur[u]; i!=-1; i=e[i].next)
     32           {
     33               j=e[i].po;
     34               if (e[i].flow>0&&h[u]==h[j]+1)
     35               {
     36                  neck=min(neck,e[i].flow);
     37                  cur[u]=i;
     38                  pre[j]=u;  u=j;
     39                  if (u==t)
     40                  {
     41                     s+=neck;
     42                     while (u)
     43                     {
     44                           u=pre[u];
     45                           j=cur[u];
     46                           e[j].flow-=neck;
     47                           e[j^1].flow+=neck;
     48                     }
     49                     neck=inf;
     50                  }
     51                  ch=0;
     52                  break;
     53               }
     54           }
     55           if (ch)
     56           {
     57              if (--numh[h[u]]==0) return s;
     58              int q=-1,tmp=t;
     59              for (int i=p[u]; i!=-1; i=e[i].next)
     60              {
     61                  j=e[i].po;
     62                  if (e[i].flow&&h[j]<tmp)
     63                  {
     64                     tmp=h[j];
     65                     q=i;
     66                  }
     67              }
     68              cur[u]=q; h[u]=tmp+1;
     69              numh[h[u]]++;
     70              if (u)
     71              {
     72                 u=pre[u];
     73                 neck=d[u];
     74              }
     75           }
     76     }
     77     return s;
     78 }
     79 
     80 int main()
     81 {
     82     while (scanf("%d%d",&n,&m)!=EOF)
     83     {
     84         len=-1;
     85         memset(p,255,sizeof(p));
     86         memset(b,0,sizeof(b));
     87         for (int i=1; i<=n; i++)
     88         {
     89             int st=0,x;
     90             for (int j=0; j<m; j++)
     91             {
     92                 scanf("%d",&x);
     93                 st|=(x&1)<<j;
     94             }
     95             b[st]++;
     96         }
     97         t=(1<<m)+m+1;
     98         for (int i=0; i<(1<<m); i++)
     99         {
    100             for (int j=0; j<m; j++)
    101                 if ((i>>j)&1) build(i+m+1,j+1,b[i]);
    102             build(0,i+m+1,b[i]);
    103         }
    104         for (int i=1; i<=m; i++)
    105         {
    106             int x;
    107             scanf("%d",&x);
    108             build(i,t,x);
    109         }
    110         if (sap()==n) puts("YES"); else puts("NO");
    111     }
    112 }
    View Code

    hdu5988

    费用取对数,简单的费用流

      1 #include<bits/stdc++.h>
      2 
      3 using namespace std;
      4 
      5 using namespace std;
      6 struct way{int po,next,flow; double cost;} e[200010];
      7 const int inf=100000007;
      8 const double eps=1e-7;
      9 int pre[110],p[110],cur[110],q[4000010];
     10 double d[110];
     11 bool v[110];
     12 int len,n,m,t,k;
     13 
     14 void add(int x,int y,int f,double c)
     15 {
     16      e[++len].po=y;
     17      e[len].flow=f;
     18      e[len].cost=c;
     19      e[len].next=p[x];
     20      p[x]=len;
     21 }
     22 
     23 void build(int x,int y, int f, double c)
     24 {
     25      add(x,y,f,c);
     26      add(y,x,0,-c);
     27 }
     28 
     29 bool spfa()
     30 {
     31      int f=1,r=1;
     32      for (int i=1; i<=t; i++) d[i]=inf;
     33      memset(v,0,sizeof(v));
     34      d[0]=0; q[1]=0;
     35      while (f<=r)
     36      {
     37            int x=q[f++];
     38            v[x]=0;
     39            for (int i=p[x]; i!=-1; i=e[i].next)
     40            {
     41                int y=e[i].po;
     42                if (e[i].flow&&d[x]+e[i].cost+eps<d[y])
     43                {
     44                   d[y]=d[x]+e[i].cost;
     45                   pre[y]=x; cur[y]=i;
     46                   if (!v[y])
     47                   {
     48                      q[++r]=y;
     49                      v[y]=1;
     50                   }
     51                }
     52            }
     53      }
     54      return d[t]<inf;
     55 }
     56 
     57 double mincost()
     58 {
     59     int j;
     60     double s=0;
     61     while (spfa())
     62     {
     63           int neck=inf;
     64           for (int i=t; i; i=pre[i])
     65           {
     66               j=cur[i];
     67               neck=min(neck,e[j].flow);
     68           }
     69           s+=d[t]*neck;
     70           for (int i=t; i; i=pre[i])
     71           {
     72               j=cur[i];
     73               e[j].flow-=neck;
     74               e[j^1].flow+=neck;
     75           }
     76     }
     77     return s;
     78 }
     79 
     80 int main()
     81 {
     82     int cas;
     83     scanf("%d",&cas);
     84     while (cas--)
     85     {
     86         scanf("%d%d",&n,&m);
     87         t=n+1; len=-1; memset(p,255,sizeof(p));
     88         for (int i=1; i<=n; i++)
     89         {
     90             int x,y;
     91             scanf("%d%d",&x,&y);
     92             if (x-y>0) build(0,i,x-y,0);
     93             else if (x-y<0) build(i,t,y-x,0);
     94         }
     95         for (int i=1; i<=m; i++)
     96         {
     97             int x,y,f; double c;
     98             scanf("%d%d%d%lf",&x,&y,&f,&c);
     99             c=-log2(1.0-c);
    100             if (f) build(x,y,1,0);
    101             if (f>1) build(x,y,f-1,c);
    102         }
    103         double ans=mincost();
    104         ans=pow(2,-ans);
    105         printf("%.2lf
    ",1.0-ans);
    106     }
    107 }
    View Code

    hdu5985

    无穷项一般要么高斯消元要么取有限项保留对应精度即可,这里只要求出h[i][k]表示第i个在第k次操作后被全部移走的概率就可以轻易计算出答案

     1 #include<bits/stdc++.h>
     2 
     3 using namespace std;
     4 double h[15][80],ans[15],p[15];
     5 int a[15],n;
     6 int main()
     7 {
     8     int cas;
     9     scanf("%d",&cas);
    10     while (cas--)
    11     {
    12         scanf("%d",&n);
    13         for (int i=1; i<=n; i++)
    14             scanf("%d%lf",&a[i],&p[i]);
    15         if (n==1)
    16         {
    17             printf("%.6lf
    ",1.0);
    18             continue;
    19         }
    20         for (int i=1; i<=n; i++)
    21         {
    22             double tmp=1.0;
    23             for (int j=1; j<=76; j++)
    24             {
    25                 tmp*=p[i];
    26                 h[i][j]=pow(1-tmp,a[i]);
    27             }
    28         }
    29         for (int i=1; i<=n; i++)
    30         {
    31             ans[i]=0;
    32             for (int k=1; k<=75; k++)
    33             {
    34                 double tmp=1.0;
    35                 for (int j=1; j<=n; j++)
    36                     if (j!=i) tmp*=h[j][k];
    37                 ans[i]+=(h[i][k+1]-h[i][k])*tmp;
    38             }
    39         }
    40         for (int i=1; i<=n; i++)
    41         {
    42             printf("%.6lf",ans[i]);
    43             if (i==n) puts(""); else printf(" ");
    44         }
    45     }
    46 }
    View Code
  • 相关阅读:
    康复计划
    Leetcode 08.02 迷路的机器人 缓存加回溯
    Leetcode 38 外观数列
    Leetcode 801 使序列递增的最小交换次数
    Leetcode 1143 最长公共子序列
    Leetcode 11 盛水最多的容器 贪心算法
    Leetcode 1186 删除一次得到子数组最大和
    Leetcode 300 最长上升子序列
    Leetcode95 不同的二叉搜索树II 精致的分治
    Leetcode 1367 二叉树中的列表 DFS
  • 原文地址:https://www.cnblogs.com/phile/p/6566105.html
Copyright © 2011-2022 走看看