• 9.10题解


    T1

    考场上有一部分答案算重了,没有判掉,然后就死了,正解是$bitset$乱搞

    记录一下每个点能够到达哪些点,然后减去他的直系儿子,就是最后对答案造成的贡献,每个点能够达到的点由他儿子传过来即可,为了避免多次无用搜索,我们从入度为0的点开始搜,这样的话可以尽量的减少重复搜索的点,但同时由于他是有向边,你还是会有点跑两遍,所以判一下,如果已经跑过了没,就不跑了,直接传信息

    但是我们会发现,我们就算用$bitset$,依旧会炸空间,考虑优化,他们是按拓扑序分层转移,而我不会,所以我搜了一半,分两次搜,一次只有前一半的点做贡献,一次只有后一半的点做贡献,把答案加起来,多余的贡献就是$n+m$,减掉就好了

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<vector>
     5 #include<bitset>
     6 #define maxx 61000
     7 #define maxn 31000
     8 #define maxm 100100
     9 using namespace std;
    10 int n,m,u,v,js,ans,mid,opt;
    11 int head[maxx],to[maxm],xia[maxm],pd[maxx],du[maxx];
    12 bitset <maxn> a[maxx];
    13 vector <int> sou;
    14 void add(int x,int y)
    15 {
    16     to[++js]=y;  xia[js]=head[x];  head[x]=js;  du[y]++;
    17 }
    18 void dfs(int x)
    19 {
    20     pd[x]=1;
    21     if(!opt&&x<=mid)  a[x][x]=1;
    22     if(opt&&x>mid)  a[x][x-mid]=1;
    23     for(int i=head[x];i;i=xia[i])
    24     {
    25         int ls=to[i];
    26         if(!pd[ls])  dfs(ls);
    27         a[x]|=a[ls];
    28     }
    29 }
    30 int main()
    31 {
    32 //    freopen("worldline2.in","r",stdin);
    33     scanf("%d%d",&n,&m);
    34     for(int i=1;i<=m;++i)  {scanf("%d%d",&u,&v);  add(u,v);}
    35     for(int i=1;i<=n;++i)
    36         if(!du[i])  sou.push_back(i);
    37     mid=n/2;
    38     for(int i=0;i<sou.size();++i)  dfs(sou[i]);
    39     for(int i=1;i<=n;++i)  {ans+=a[i].count();  a[i].reset();}
    40     memset(pd,0,sizeof(pd));  opt=1;
    41     for(int i=0;i<sou.size();++i)  dfs(sou[i]);
    42     for(int i=1;i<=n;++i)  {ans+=a[i].count();  a[i].reset();}
    43     printf("%d
    ",ans-m-n);
    44     return 0;
    45 }
    bitset搜一半非常好用

    T2

    考场上想到了贪心,但是由于$STL$玩的不够溜,没敢用$set$,手动找的转移点,然后就找死了

    我想的贪心是找范围最靠近这个节点的电阻,放给他,这样我就会有左端点,右端点两种限制,考虑怎么可以去掉一个,等等,先离散化一下再继续,因为我们需要用范围当下标,离散化之后,把电阻和节点信息全部按左端点从小到大排序,然后扫每一个节点,如果当前有左节点符合条件的电阻,就把右端点扔进$set$里,这样的话$set$里是所有可用电阻,左端点就不会造成限制了,我们就成功去掉了一个限制,在保证左端点合法的$set$中,$lower$_$bound$出最靠左的右端点合法的位置,放满这个节点,或没有可以放在这个节点的电阻之后进入下一个节点即可,由于$set$自动去重,所以需要开个桶看右端点在这个位置的电阻有多少个,或许$multiset$也可以吧

     1 #include<algorithm>
     2 #include<iostream>
     3 #include<cstring>
     4 #include<cstdio>
     5 #include<set>
     6 #define maxn 50100
     7 using namespace std;
     8 struct node{
     9     int l,r,num;
    10 }nn[maxn],mm[maxn];
    11 int lsh[maxn*8],tong[maxn*8];
    12 int T,n,m,bj,head,tot,len;
    13 set <int> s;
    14 inline int read()
    15 {
    16     int e=0;  char ch=getchar();
    17     while(ch<'0'||ch>'9')  ch=getchar();
    18     while(ch>='0'&&ch<='9')  {e=(e<<3)+(e<<1)+(ch^48);  ch=getchar();}
    19     return e;
    20 }
    21 bool cmp(const node &a,const node &b)
    22 {
    23     return a.l<b.l;
    24 }
    25 void clear()
    26 {
    27     bj=0;  head=1;  tot=0;  s.clear();
    28     memset(nn,0,sizeof(nn));  memset(mm,0,sizeof(mm));
    29     memset(lsh,0,sizeof(lsh));  memset(tong,0,sizeof(tong));
    30 }
    31 int main()
    32 {
    33     T=read();
    34     while(T--)
    35     {
    36         n=read();  m=read();  clear();
    37         for(int i=1;i<=n;++i)
    38         {
    39             nn[i].l=read();  nn[i].r=read();  nn[i].num=read();
    40             lsh[++tot]=nn[i].l;  lsh[++tot]=nn[i].r;
    41         }
    42         for(int i=1;i<=m;++i)
    43         {
    44             mm[i].l=read();  mm[i].r=read();  mm[i].num=read();
    45             lsh[++tot]=mm[i].l;  lsh[++tot]=mm[i].r;
    46         }
    47         sort(lsh+1,lsh+tot+1);
    48         len=unique(lsh+1,lsh+tot+1)-lsh-1;
    49         for(int i=1;i<=n;++i)
    50         {
    51             nn[i].l=lower_bound(lsh+1,lsh+len+1,nn[i].l)-lsh;
    52             nn[i].r=lower_bound(lsh+1,lsh+len+1,nn[i].r)-lsh;
    53         }
    54         for(int i=1;i<=m;++i)
    55         {
    56             mm[i].l=lower_bound(lsh+1,lsh+len+1,mm[i].l)-lsh;
    57             mm[i].r=lower_bound(lsh+1,lsh+len+1,mm[i].r)-lsh;
    58         }
    59         sort(nn+1,nn+n+1,cmp);  sort(mm+1,mm+m+1,cmp);
    60         for(int i=1;i<=n;++i)
    61         {
    62             while(mm[head].l<=nn[i].l&&head<=m)
    63             {
    64                 s.insert(mm[head].r);  tong[mm[head].r]+=mm[head].num;  head++;
    65             }
    66             while(1)
    67             {
    68                 if(nn[i].num==0)  break;
    69                 set<int>::iterator it=s.lower_bound(nn[i].r);
    70                 if(it==s.end())  break;
    71                 int ji=min(nn[i].num,tong[*it]);
    72                 nn[i].num-=ji;  tong[*it]-=ji;
    73                 if(!tong[*it])  s.erase(it);
    74             }
    75         }
    76         for(int i=1;i<=n;++i)
    77             if(nn[i].num)  {bj=1;  break;}
    78         if(bj)  printf("No
    ");
    79         else  printf("Yes
    ");
    80     }
    81     return 0;
    82 }
    View Code

    T3

    不会做,咕咕咕人类的本质就是咕咕咕

  • 相关阅读:
    Linq聚合操作之Aggregate,Count,Sum,Distinct源码分析
    Linq分区操作之Skip,SkipWhile,Take,TakeWhile源码分析
    Linq生成操作之DefautIfEmpty,Empty,Range,Repeat源码分析
    Linq基础操作之Select,Where,OrderBy,ThenBy源码分析
    PAT 1152 Google Recruitment
    PAT 1092 To Buy or Not to Buy
    PAT 1081 Rational Sum
    PAT 1084 Broken Keyboard
    PAT 1077 Kuchiguse
    PAT 1073 Scientific Notation
  • 原文地址:https://www.cnblogs.com/hzjuruo/p/11626486.html
Copyright © 2020-2023  润新知