zoukankan      html  css  js  c++  java
  • 模拟10题解

    T1[辣鸡(ljh)]「暴力」

    第一个测试点启发选手想出,要分矩形内部和矩形相接处的来计算

    内部的显然是(长-1)×(宽-1)×2

    相接处:先按照(x,xx)进行二元组排序,可以大大减少情况数,见代码

     

    T3[大佬(kat)]「概率DP」

    和模拟9的T1的DP差不多

    定义$f[i][j]$表示第i天后,最大难度值为j的方案数

    转移:1:到i-1天时最大值已经j,则第i天可以为1~j,$f[i-1][j]*j$

            2:到i-1时最大值不是j,第i天j是最大,$sum limits_ {k=1}^{j-1}f[i-1][k]$

      $f[i][j]=f[i-1][j]*j+sum limits_{k=1}^{j-1} f[i-1][k]$  时间复杂度$O(n^3)$

    最终答案:

      对于每k天的劳累值:

          每天有m种情况,k天就是$m^k$中情况

          所以 $frac{sumlimits_{j=1}^{m}f[k][j]*w[j]}{m^k}$

    在总的$n-k+1$天中每天是相同的

         最终答案:ans=$(n-k+1)*frac{sumlimits_{j=1}^{m}f[k][j]*w[j]}{m^k}$

    当然可以稍做简化,不用dp,

    在k天中,i^k 是 最大难度值可能是i,但不可能是更大的情况数,(i-1)^k同理,那么相减就是最大值为i的方案数

    方案数就是  $frac{sumlimits_{j=1}^{m} j^k-(j-1)^k*w[j]}{m^k}$

    T2[B.模板(ac)]

    30%算法:暴力

    另40%算法:「动态开点」「线段树合并」

    考虑到k=1e5的情况,此时不用管小桶,就是求往里放了多少,跟「雨天的尾巴」一样

    先将颜色离散化

    对每个节点,开一个动态开点的,维护放入的颜色个数(也是种类)的线段树,

    读入时将将颜色种类插入,dfs再进行合并子树

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<cmath>
      5 #include<set>
      6 #include<algorithm>
      7 #define mid ((l+r)>>1)
      8 using namespace std;
      9 int read()
     10 {
     11     int f=1,x=0;char ch=getchar();
     12     while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
     13     while(ch<='9'&&ch>='0'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
     14     return f*x;
     15 }
     16 const int maxn=1e5+5;
     17 int cn;
     18 int k[maxn],fa[maxn],c[maxn],cc[maxn],pos[maxn],ans[maxn];
     19 int tot,rt[40*maxn],lc[40*maxn],rc[40*maxn],sum[40*maxn];
     20 set<int>c1[maxn];
     21 struct node{
     22     int v,nxt;
     23 }e[2*maxn];int nu,h[maxn];
     24 void add(int x,int y)
     25 {
     26     e[++nu].v=y;
     27     e[nu].nxt=h[x];
     28     h[x]=nu;
     29 }
     30 void predfs(int x,int f)
     31 {
     32     fa[x]=f;
     33     for(int i=h[x];i;i=e[i].nxt)
     34     {
     35         int y=e[i].v;
     36         if(y==f)continue;
     37         predfs(y,x);
     38     }
     39 }
     40 void insert(int &root,int l,int r,int w)
     41 {
     42     if(!root)  root=++tot;
     43     if(l==r){sum[root]=1;return;}
     44     if(w<=mid)    insert(lc[root],l,mid,w);
     45     else     insert(rc[root],mid+1,r,w);
     46     sum[root]=sum[lc[root]]+sum[rc[root]];
     47 }
     48 int merge(int x,int y,int l,int r)
     49 {
     50     if(!x||!y)return x+y;
     51     if(l==r)return x;
     52     lc[x]=merge(lc[x],lc[y],l,mid);
     53     rc[x]=merge(rc[x],rc[y],mid+1,r);
     54     sum[x]=sum[lc[x]]+sum[rc[x]];
     55     return x;
     56 }
     57 void dfs(int x,int f)
     58 {
     59     for(int i=h[x];i;i=e[i].nxt)
     60     {
     61         int y=e[i].v;
     62         if(y==f)continue;
     63         dfs(y,x);
     64         rt[x]=merge(rt[x],rt[y],1,cn);
     65     }
     66     ans[x]=sum[rt[x]];
     67 }
     68 int main()
     69 {
     70     //freopen("data","r",stdin);
     71     const int n=read();
     72     for(int i=1;i<n;i++)
     73     {
     74         int x=read(),y=read();
     75         add(x,y);add(y,x);
     76     }
     77     predfs(1,0);
     78     for(int i=1;i<=n;i++)     k[i]=read();
     79     const int m=read();
     80     if(n<=1000&&m<=1000)
     81     {
     82         for(int i=1;i<=m;i++)
     83         {
     84             int x=read(),col=read();
     85             while(x)
     86             {
     87                 if(k[x])
     88                 {
     89                     k[x]--;
     90                     if(c1[x].find(col)==c1[x].end())
     91                     {
     92                         c1[x].insert(col);
     93                         ans[x]++;
     94                     }
     95                 }
     96                 x=fa[x];
     97             }
     98         }
     99     }
    100     else
    101     {
    102         for(int i=1;i<=m;i++)     pos[i]=read(),c[i]=read(),cc[i]=c[i];
    103         sort(cc+1,cc+m+1);
    104         cn=unique(cc+1,cc+m+1)-cc-1;
    105         for(int i=1;i<=m;i++)
    106         {
    107             c[i]=lower_bound(cc+1,cc+cn+1,c[i])-cc;
    108             insert(rt[pos[i]],1,cn,c[i]);
    109         }
    110         dfs(1,0);
    111     }
    112     int Q=read();
    113     while(Q--)
    114     {
    115         int x=read();
    116         printf("%d
    ",ans[x]);
    117     }
    118 }
    119 /*
    120 g++ 2.cpp -o 2
    121 ./2
    122 
    123 */
    View Code

    100%算法:

    注意: 普通的线段树,只开一个,重复使用

    对于每个操作:x,col,  vector<int> ty[x]存x节点的放入颜色种类,ti[x]存放入时间

    predfs出1,每个点即将放入的小球个数size(不考虑k的限制)2,重儿子(size最大)的标号

    统计答案(dfs):思想:

    先处理子节点(先轻儿子,后重儿子),(递归回来后要不断对线段树清空)

    然后依次在线段树中插入(inser)重儿子,自己,和轻儿子的信息,

    然后就可以查询(query)了

    之后将x,和轻儿子的信息合并(merge)到重儿子身上,以供父节点使用

    (将轻的向重的上合并,这就是启发式合并的思想)

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<cmath>
      5 #include<set>
      6 #include<algorithm>
      7 #include<vector>
      8 #define mid ((l+r)>>1)
      9 #define lc (x<<1)
     10 #define rc (x<<1|1)
     11 using namespace std;
     12 int read()
     13 {
     14     int f=1,x=0;char ch=getchar();
     15     while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
     16     while(ch<='9'&&ch>='0'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
     17     return f*x;
     18 }
     19 const int maxn=5e5+5;
     20 int cn,m;
     21 int k[maxn],cc[maxn],ans[maxn],son[maxn];
     22 int size[10*maxn],an[10*maxn],siz[10*maxn],lazy[10*maxn],t[10*maxn];
     23 vector<int>ty[10*maxn];
     24 vector<int>ti[10*maxn];
     25 struct node{
     26     int v,nxt;
     27 }e[2*maxn];int nu,h[maxn];
     28 inline void add(int x,int y)
     29 {
     30     e[++nu].v=y;
     31     e[nu].nxt=h[x];
     32     h[x]=nu;
     33 }
     34 void predfs(int x,int f)//预处理出子树的大小和重儿子
     35 {
     36     size[x]=ty[x].size();
     37     for(int i=h[x];i;i=e[i].nxt)
     38     {
     39         int y=e[i].v;
     40         if(y==f)continue;
     41         predfs(y,x);
     42         size[x]+=size[y];
     43         if(size[y]>size[son[x]])
     44             son[x]=y;
     45     }
     46 }
     47 inline void pushdown(int x)
     48 {//将x的儿子节点清空,避免了每次的全部清空
     49     lazy[lc]=lazy[rc]=1;
     50     lazy[x]=an[lc]=an[rc]=siz[lc]=siz[rc]=0;
     51 }
     52 inline void pushup(int x)
     53 {
     54     an[x]=an[lc]+an[rc];
     55     siz[x]=siz[lc]+siz[rc];
     56 }
     57 inline void updata(int x,int l,int r,int val,int derta,int sum)
     58 {
     59     an[x]+=derta,siz[x]+=sum;
     60     if(l==r)return;
     61     if(lazy[x]) pushdown(x);
     62     if(val<=mid)updata(lc,l,mid,val,derta,sum);
     63     else         updata(rc,mid+1,r,val,derta,sum);
     64     pushup(x);
     65 }
     66 inline int query(int x,int l,int r,int sum)
     67 {
     68     if(sum<=0)return 0 ;
     69     if(l==r) return an[x];
     70     if(lazy[x])  pushdown(x);
     71     if(siz[lc]<=sum)
     72         return an[lc]+query(rc,mid+1,r,sum-siz[lc]);
     73     else
     74         return query(lc,l,mid,sum);
     75 }
     76 inline void merge(int x,int y)
     77 {
     78     for(int i=0;i<ty[y].size();i++)
     79         ty[x].push_back(ty[y][i]),ti[x].push_back(ti[y][i]);
     80     ty[y].clear(),ti[y].clear();
     81 }
     82 inline void clea(int x)//清空维护时间的线段树,用lazy标记,不全清
     83 {//an答案数组  siz线段树子树大小
     84     an[1]=siz[1]=0,lazy[1]=1;//标记是否需要用的时候清空
     85     for(int i=0;i<ty[x].size();i++)
     86         t[ty[x][i]]=0;//t维护color的出现时间
     87 }
     88 inline void inser(int x)
     89 {
     90     for(int i=0;i<ty[x].size();i++)
     91     {
     92         int col=ty[x][i],tim=ti[x][i];
     93         if(!t[col])updata(1,1,m,tim,1,0),t[col]=tim;
     94         else if(t[col]>tim)
     95         {
     96             updata(1,1,m,t[col],-1,0);//把时间靠后的小球对an做的贡献减掉
     97             updata(1,1,m,tim,1,0);//把时间靠前到小球对an的贡献加上,但是都不改变个数
     98             t[col]=tim;
     99         }
    100         updata(1,1,m,tim,0,1);//最后加上这一个的个数
    101     }
    102 }
    103 void dfs(int x,int f)
    104 {
    105     for(int i=h[x];i;i=e[i].nxt)
    106     {
    107         int y=e[i].v;
    108         if(son[x]==y||y==f)continue;
    109         dfs(y,x);
    110         clea(y);//清空线段树的信息
    111     }
    112     if(son[x])    dfs(son[x],x);//遍历完所有儿子,最后遍历重儿子,且线段树中存有重儿子信息
    113     inser(x);//把x的信息放入线段树
    114     for(int i=h[x];i;i=e[i].nxt)
    115     {
    116         int y=e[i].v;
    117         if(y==f||y==son[x])continue;
    118         inser(y);//把y节点的信息放入线段树
    119     }
    120     ans[x]=query(1,1,m,k[x]);
    121     if(son[x])
    122     {
    123         merge(son[x],x);//将x和重儿子节点信息合并
    124         swap(ty[son[x]],ty[x]),swap(ti[son[x]],ti[x]);
    125         for(int i=h[x];i;i=e[i].nxt)
    126         {
    127             int y=e[i].v;
    128             if(y==f)continue;
    129             merge(x,y);//合并轻儿子
    130         }
    131     }
    132 }
    133 int main()
    134 {    
    135 //    freopen("data","r",stdin);
    136     const int n=read();
    137     for(int i=1;i<n;i++)
    138     {
    139         int x=read(),y=read();
    140         add(x,y),add(y,x);
    141     }
    142     for(int i=1;i<=n;i++)     k[i]=read();
    143     m=read();
    144     for(int i=1;i<=m;i++)
    145     {
    146         int x=read(),col=read();
    147         if(cc[col]==0) cc[col]=++cn;
    148         col=cc[col];//将颜色离散化
    149         ty[x].push_back(col),ti[x].push_back(i);
    150         //ty存颜色种类,ti存该颜色放入的时间
    151     }
    152     predfs(1,0);
    153     dfs(1,0);
    154     int Q=read();
    155     while(Q--)
    156     {
    157         int x=read();
    158         printf("%d
    ",ans[x]);
    159     }
    160 }
    View Code

    愿你在迷茫时,记起自己的珍贵。
  • 相关阅读:
    phpcms新建模板页教程
    Linux方向职业规划
    Codeforces Round #417 (Div. 2)-A. Sagheer and Crossroad
    Codeforces Round #396(Div. 2) A. Mahmoud and Longest Uncommon Subsequence
    ACM hdu 3336 Count the string
    ACM KMP 格式输入导致TLE
    swing JTable 更新数据
    swing JTable
    HashMap 和 HashTable 区别
    Java中next()和nextLine()
  • 原文地址:https://www.cnblogs.com/casun547/p/11272484.html
Copyright © 2011-2022 走看看