7.30 NOIP模拟10

T1.辣鸡

  考试的时候竟然被我以“麻烦”弃掉了,赛后发现这题好水啊,直接sort一下寻找四周即可。

T2.模板

  考试时期望得分70,实际得分5

  首先看到这种题基本就是线段树,我们以时间为下标,对每一个点种一棵线段树,在dfs时向上合并,同时维护出每个点的子树中每种颜色第一次出现的位置(用数组,map都行)

给每一个节点开一个vector,直接向上传递vector,并且将vector中的所有元素插入父节点的线段树中,并更新颜色出现的最早位置,将更晚的球清掉即可。

  在向上合并时,我们采用启发式合并的方式来保障复杂度,对于每个点,将其所有轻儿子和并入它的重儿子(带有信息最多的儿子)中,即可保证合并的复杂度不会爆炸。

T3.大佬

  假期望,求出所有的劳累值之和除以总情况数即可。

  所以我们只要求出最大难度为j的方案数即可。

  简单粗暴,dp或者直接快速幂容斥都行。

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 map<int,int>g[100005];
  4 vector<pair<int,int> >gg[000005];
  5 int rc[5000005],sum[5000005],q,ans[100005],ttt,siz[100005],ss[5000005],mm[100005],mmm[100005];
  6 int n,m,tt,fi[100005],ne[200005],to[200005],tot,a[100005],f[100005],d[100005],r[100005],lc[5000005];
  7 inline void add(int x,int y)
  8 {
  9     ne[++tot]=fi[x];
 10     fi[x]=tot;
 11     to[tot]=y;
 12 }
 13 void insert(int &x,int l,int r,int pos,int val)
 14 {
 15     if(!x)x=++tt;
 16     if(l==r)
 17     {
 18         if(val==2)sum[x]++;
 19         if(val==1)sum[x]++,ss[x]=1;
 20         if(val==-1)ss[x]=0;
 21         return;
 22     }
 23     int mid=(l+r)>>1;
 24     if(pos<=mid)insert(lc[x],l,mid,pos,val);
 25     else insert(rc[x],mid+1,r,pos,val);
 26     sum[x]=sum[lc[x]]+sum[rc[x]];
 27     ss[x]=ss[lc[x]]+ss[rc[x]];
 28 }
 29 int query(int x,int l,int r,int val)
 30 {
 31     if(!x)return 0;
 32     if(sum[x]<=val) return ss[x];
 33     int mid=(l+r)>>1;
 34     if(sum[lc[x]]>=val)return query(lc[x],l,mid,val);
 35     return query(rc[x],mid+1,r,val-sum[lc[x]])+ss[lc[x]];
 36 }
 37 void dfs2(int x,int fa)
 38 {
 39     for(int i=fi[x];i;i=ne[i])
 40     {
 41         int y=to[i];
 42         if(y!=fa)
 43         {
 44             dfs2(y,x);
 45             siz[x]+=siz[y];
 46             if(siz[y]>siz[mm[x]])
 47                 mm[x]=y;
 48         }
 49     }
 50     if(mm[x])
 51     {
 52         mmm[x]=mmm[mm[x]];
 53         for(int i=0;i<gg[x].size();i++)
 54         {
 55             int f=gg[x][i].first,se=gg[x][i].second;
 56             gg[mmm[x]].push_back(gg[x][i]);
 57             if(g[mmm[x]][se]>f)
 58                 insert(r[mmm[x]],1,m,g[mmm[x]][se],-1),
 59                 insert(r[mmm[x]],1,m,f,1),g[mmm[x]][se]=f;
 60             else if(g[mmm[x]][se]==0)
 61                 insert(r[mmm[x]],1,m,f,1),g[mmm[x]][se]=f;
 62             if(g[mmm[x]][se]<f) insert(r[mmm[x]],1,m,f,2);
 63         }
 64         for(int i=fi[x];i;i=ne[i])
 65         {
 66             int y=to[i];
 67             if(y!=fa&&y!=mm[x])
 68             {
 69                 for(int j=0;j<gg[mmm[y]].size();j++)
 70                 {
 71                     int se=gg[mmm[y]][j].first,f=gg[mmm[y]][j].second;
 72                     gg[mmm[x]].push_back(gg[mmm[y]][j]);
 73                     if(g[mmm[x]][f]>se)
 74                         insert(r[mmm[x]],1,m,g[mmm[x]][f],-1),
 75                         insert(r[mmm[x]],1,m,se,1),g[mmm[x]][f]=se;
 76                     else if(g[mmm[x]][f]==0)
 77                         insert(r[mmm[x]],1,m,se,1),g[mmm[x]][f]=se;
 78                     if(g[mmm[x]][f]<se) insert(r[mmm[x]],1,m,se,2);
 79                 }
 80             }
 81         }
 82     }
 83     ans[x]=query(r[mmm[x]],1,m,a[x]);
 84 }
 85 int main()
 86 {
 87     scanf("%d",&n);
 88     for(int i=1,x,y;i<n;i++)
 89     {
 90         scanf("%d%d",&x,&y);
 91         add(x,y),add(y,x);
 92     }
 93     for(int i=1;i<=n;i++)
 94         scanf("%d",&a[i]);
 95     scanf("%d",&m);
 96     for(int i=1,x,y;i<=m;i++)
 97     {
 98         scanf("%d%d",&x,&y);siz[x]++;
 99         gg[x].push_back(make_pair(i,y));
100         if(g[x][y]==0)g[x][y]=i,insert(r[x],1,m,i,1);
101         else insert(r[x],1,m,i,2);
102     }
103     for(int i=1;i<=n;i++)mmm[i]=i;
104     siz[0]=-1;dfs2(1,0);
105     scanf("%d",&q);
106     for(int i=1,x;i<=q;i++)
107         scanf("%d",&x),printf("%d\n",ans[x]);
108     return 0;
109 }
模板题

 

转载于:https://www.cnblogs.com/hzoi-cbx/p/11269621.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值