zoukankan      html  css  js  c++  java
  • 5.27 Test

    1.COGS.2039. 树的统计

    思路:

       各种方法。

    代码:

     1.遍历树1   时间 0.314 s   平均内存 2.96 MB

     1 #include<cstdio>
     2 using namespace std;
     3 const int N=100005;
     4 
     5 int n,Enum,cnt,H[N<<1],fa[N],Ans;//,Dfn[N],Size[N];
     6 struct Edge
     7 {
     8     int to,nxt;
     9 }e[N<<1];
    10 
    11 int read()
    12 {
    13     int now=0;bool f=0;char c=getchar();
    14     while(c<'0'||c>'9')
    15     {
    16         if(c=='-')f=1;
    17         c=getchar();
    18     }
    19     while(c>='0'&&c<='9')now=(now<<3)+(now<<1)+c-'0',c=getchar();
    20     return f?-now:now;
    21 }
    22 
    23 void AddEdge(int u,int v)
    24 {
    25     e[++Enum].to = v;
    26     e[Enum].nxt = H[u];
    27     H[u] = Enum;
    28 }
    29 
    30 void DFS(int cur,int f,int cmp)
    31 {
    32 //    Dfn[cur]=++cnt;//printf("%d:%d
    ",cnt,cur);
    33     for(int i=H[cur];i;i=e[i].nxt)
    34     {
    35         int to=e[i].to;//printf("%d OK
    ",cur);
    36         if(to!=f)
    37         {
    38             if(to<cmp) ++Ans;
    39             DFS(to,cur,cmp);
    40 //            Ans[cur]+=Ans[to];
    41 //            Size[cur]+=Size[to]+1;
    42         }
    43     }
    44 }
    45 
    46 int main()
    47 {
    48 //    freopen("counttree.in","r",stdin);
    49 //    freopen("counttree.out","w",stdout);
    50     n=read();
    51     int sta;
    52     for(int i=1;i<=n;i++)
    53     {
    54         fa[i]=read();
    55         if(fa[i]==0) sta=i;
    56         else AddEdge(fa[i],i),AddEdge(i,fa[i]);
    57     }
    58 //    DFS(sta,0);
    59 //    printf("%d ",sta);
    60 //    for(int i=1;i<=n;i++)
    61 //      printf("%d ",Ans[i]);
    62     for(int i=1;i<=n;i++)
    63     {
    64         Ans=0;
    65         DFS(i,fa[i],i);
    66         printf("%d
    ",Ans);
    67     }
    68     fclose(stdin);fclose(stdout);
    69     return 0;
    70 }
    View Code

    2.遍历父节点   时间 0.151 s  平均内存 1.05 MB

     1 #include<cstdio>
     2 using namespace std;
     3 const int N=100005;
     4 
     5 int n,fa[N],Num[N];
     6 
     7 int read()
     8 {
     9     int now=0;bool f=0;char c=getchar();
    10     while(c<'0'||c>'9')
    11     {
    12         if(c=='-')f=1;
    13         c=getchar();
    14     }
    15     while(c>='0'&&c<='9')now=(now<<3)+(now<<1)+c-'0',c=getchar();
    16     return f?-now:now;
    17 }
    18 
    19 int main()
    20 {
    21     freopen("counttree.in","r",stdin);
    22     freopen("counttree.out","w",stdout);
    23     n=read();
    24     for(int a,i=1;i<=n;i++)
    25       a=read(),fa[i]=a;
    26     for(int i=1;i<=n;i++)
    27     {
    28         int t=i;
    29         while(fa[t])
    30         {
    31             if(fa[t]>i)
    32               ++Num[fa[t]];
    33             t=fa[t];
    34         }
    35     }
    36     for(int i=1;i<=n;i++)
    37       printf("%d
    ",Num[i]);
    38     fclose(stdin);fclose(stdout);
    39     return 0;
    40 }
    View Code

    3.DFS序+树状数组(参考)   时间 0.154 s  内存使用 3.72MB

     1 #include<cstdio>
     2 using namespace std;
     3 const int N=100005;
     4 
     5 int n,Enum,cnt,in[N],out[N],H[N<<1],Tree[N];
     6 struct Edge
     7 {
     8     int to,nxt;
     9 }e[N<<1];
    10 
    11 int read()
    12 {
    13     int now=0;bool f=0;char c=getchar();
    14     while(c<'0'||c>'9')
    15     {
    16         if(c=='-')f=1;
    17         c=getchar();
    18     }
    19     while(c>='0'&&c<='9')now=(now<<3)+(now<<1)+c-'0',c=getchar();
    20     return f?-now:now;
    21 }
    22 
    23 void AddEdge(int u,int v)
    24 {
    25     e[++Enum].to = v;
    26     e[Enum].nxt = H[u];
    27     H[u] = Enum;
    28 }
    29 
    30 void DFS(int cur,int f)
    31 {
    32     in[cur]=++cnt;
    33     for(int i=H[cur];i;i=e[i].nxt)
    34     {
    35         int to=e[i].to;
    36         if(to!=f)
    37           DFS(to,cur);
    38     }
    39     out[cur]=cnt;
    40 }
    41 
    42 inline int lb(int x)
    43 {
    44     return x&-x;
    45 }
    46 void Update(int p,int v)
    47 {
    48     while(p<=n)
    49       Tree[p]+=v,p+=lb(p);
    50 }
    51 int Query(int p)
    52 {
    53     int tmp=0;
    54     while(p)
    55       tmp+=Tree[p],p-=lb(p);
    56     return tmp;
    57 }
    58 
    59 int main()
    60 {
    61     freopen("counttree.in","r",stdin);
    62     freopen("counttree.out","w",stdout);
    63     n=read();
    64     int sta;
    65     for(int a,i=1;i<=n;i++)
    66     {
    67         a=read();
    68         if(!a)
    69           sta=i;
    70         else
    71           AddEdge(a,i),AddEdge(i,a);
    72     }
    73     DFS(sta,-1);
    74     for(int i=1;i<=n;i++)
    75     {
    76         printf("%d
    ",Query(out[i])-Query(in[i]-1));
    77         Update(in[i],1);
    78     }
    79     fclose(stdin);fclose(stdout);
    80     return 0;
    81 }
    View Code

    2.COGS.1682. [HAOI2014]贴海报

    思路:

      看到这题就想起zhx讲过,当时好像是用并查集做的?然而题目数据范围1e7,没敢用(也不知怎么写==),就用的分块(其实也是暴力,然而写错了点,比暴力还低4分)。

      正解:1.线段树:维护区间是否被染色:区间修改没被染色的点,标记,++ans;如果区间的点全被染过色,那ans不变。

       2.浮水法:网上并不能搜到很多东西。一篇有关博客:http://www.cnblogs.com/SueMiller/archive/2011/08/05/2128794.html

    代码:

    1.线段树:时间:0.127s  内存使用:38.44MiB

     1 #include<cmath>
     2 #include<cstdio>
     3 #include<algorithm>
     4 using namespace std;
     5 const int N=10000005,M=1005;
     6 
     7 int n,m,Ans,A[M],B[M];
     8 bool flag,colored[N<<2];
     9 
    10 int read()
    11 {
    12     int now=0;char c=getchar();
    13     while(c<'0'||c>'9')c=getchar();
    14     while(c>='0'&&c<='9')now=(now<<3)+(now<<1)+c-'0',c=getchar();
    15     return now;
    16 }
    17 
    18 void PushUp(int rt)
    19 {
    20     colored[rt]= colored[rt<<1]&&colored[rt<<1|1];
    21 }
    22 
    23 /*void Build(int l,int r,int rt)
    24 {
    25     if(l==r)
    26       return;
    27     int m=(l+r)>>1;
    28     Build(l,m,rt<<1);
    29     Build(m+1,r,rt<<1|1);
    30     PushUp(rt);
    31 }*/
    32 
    33 void Modify(int l,int r,int rt,int L,int R)
    34 {
    35     if(colored[rt]) return;
    36     if(L<=l && r<=R)
    37     {
    38         flag=1;colored[rt]=1;
    39         return;
    40     }
    41     int m=(l+r)>>1;
    42     if(L<=m) Modify(l,m,rt<<1,L,R);
    43     if(m<R) Modify(m+1,r,rt<<1|1,L,R);
    44     PushUp(rt);
    45 }
    46 
    47 int main()
    48 {
    49     freopen("ha14d.in","r",stdin);
    50     freopen("ha14d.out","w",stdout);
    51     n=read();m=read();
    52 //    Build(1,n,1);
    53     for(int i=1;i<=m;i++)
    54       A[i]=read(),B[i]=read();
    55     for(int i=m;i>=1;i--)
    56     {
    57         flag=0;
    58         Modify(1,n,1,A[i],B[i]);
    59         if(flag) ++Ans;
    60     }
    61     printf("%d",Ans);
    62     fclose(stdin);fclose(stdout);
    63     return 0;
    64 }/*
    65 1000 12
    66 1 100
    67 50 80
    68 80 99
    69 50 98
    70 1 56
    71 100 200
    72 200 300
    73 300 500
    74 500 600
    75 600 1000
    76 260 560
    77 160 580
    78 */
    线段树

    2.浮水法:时间:0.015s  内存使用:0.30MiB

     1 #include<cstdio>
     2 using namespace std;
     3 const int N=10000005,M=1005;
     4 
     5 int n,m,Ans,cur,A[M],B[M];
     6 bool vis[M];
     7 
     8 int read()
     9 {
    10     int now=0;char c=getchar();
    11     while(c<'0'||c>'9')c=getchar();
    12     while(c>='0'&&c<='9')now=(now<<3)+(now<<1)+c-'0',c=getchar();
    13     return now;
    14 }
    15 
    16 void Solve(int a,int b,int now)
    17 {
    18     if(vis[cur]) return;
    19     while(now<=m && (a>=B[now]||b<=A[now]))//需要等于 
    20       ++now;
    21     if(now>m)
    22     {
    23         ++Ans,vis[cur]=1;//printf("%d:%d--%d
    ",Ans,a,b);
    24         return;
    25     }
    26     if(a<A[now] && A[now]<b) Solve(a,A[now],now+1);//不能等于 
    27     if(b>B[now] && B[now]>a) Solve(B[now],b,now+1);
    28 }
    29 
    30 int main()
    31 {
    32 //    freopen("ha14d.in","r",stdin);
    33 //    freopen("ha14d.out","w",stdout);
    34     n=read();m=read();
    35     for(int i=1;i<=m;i++)
    36       A[i]=read(),B[i]=read(),++B[i];//右端点再加1,因为两端点是都不能放其他海报的(看不见) 
    37     for(cur=m-1;cur>=1;cur--)
    38       Solve(A[cur],B[cur],cur+1);
    39     printf("%d",++Ans);
    40 //    fclose(stdin);fclose(stdout);
    41     return 0;
    42 }
    浮水法

    3.76分的分块(懒得纠正了)

     1 #include<cmath>
     2 #include<cstdio>
     3 #include<algorithm>
     4 using namespace std;
     5 const int N=10000005,M=1005;
     6 
     7 int n,m,Ans,Size,Blo[N],A[M],B[M];
     8 bool flag,colblo[10000],colored[N];
     9 
    10 int read()
    11 {
    12     int now=0;char c=getchar();
    13     while(c<'0'||c>'9')c=getchar();
    14     while(c>='0'&&c<='9')now=(now<<3)+(now<<1)+c-'0',c=getchar();
    15     return now;
    16 }
    17 
    18 void Solve(int a,int b)
    19 {
    20     flag=0;
    21     int ba=Blo[a],bb=Blo[b];
    22     if(!colblo[ba])
    23       for(int i=a;i<=min(a*Size,b);i++)
    24         if(!colored[i])
    25           colored[i]=1,flag=1;
    26     if(ba!=bb && !colblo[bb])
    27       for(int i=(bb-1)*Size+1;i<=b;i++)
    28         if(!colored[i])
    29           colored[i]=1,flag=1;
    30     for(int i=ba+1;i<=bb-1;i++)
    31       if(!colblo[i])//当一些点把一整块覆盖时,无法有效判断. 
    32         colblo[i]=1,flag=1;
    33     if(flag) ++Ans;//printf("l:%d  r:%d
    ",a,b);
    34 }
    35 
    36 int main()
    37 {
    38 //    freopen("ha14d.in","r",stdin);
    39 //    freopen("ha14d.out","w",stdout);
    40     n=read();m=read();
    41     Size=sqrt(n);
    42     for(int i=1;i<=n;i++)
    43       Blo[i]=(i-1)/Size+1;
    44     for(int i=1;i<=m;i++)
    45       A[i]=read(),B[i]=read();
    46     for(int i=m;i>=1;i--)
    47       Solve(A[i],B[i]);
    48 //    printf("%d
    ",Blo[n]);
    49 //    for(int i=1;i<=Blo[n];i++)
    50 //      printf("%d:All:%d
    ",i,(int)colblo[i]);
    51     printf("%d",Ans);
    52     fclose(stdin);fclose(stdout);
    53     return 0;
    54 }
    76

    3.COGS.1619. [HEOI2012]采花

    思路:

       一眼就看出是个莫队,然而之前没看我不会写==。果断三分钟敲出暴力。

      正解:1.学了莫队 用莫队写了一遍,过了==好简单。。5s限时可以的。

      2.树状数组:

      这题首先在线是没法做的,所以我们可以考虑离线算法

      首先记录下每种颜色的下一种颜色所在的位置

      将所有询问按照左端点进行排序

      将所有颜色的第一个点x a[x]++

      然后从左往右扫

      扫到一个点x将a[next[x]]++

      碰到一个询问l,r输出sum[r]-sum[l-1]

      其中sum是a数组的前缀和

      求前缀和可以用树状数组(是不是很眼熟,没错摘自黄学长博客

    代码:

     1.莫队   时间:15.293s  内存使用:23.18MiB

     1 #include<cmath>
     2 #include<cstdio>
     3 #include<algorithm>
     4 using namespace std;
     5 const int N=1000005;
     6 
     7 int n,c,m,size,color[N],Times[N],now,ans[N];
     8 struct Ques
     9 {
    10     int l,r,id;
    11 }q[N];
    12 
    13 int read()
    14 {
    15     int now=0;char c=getchar();
    16     while(c<'0'||c>'9')c=getchar();
    17     while(c>='0'&&c<='9')now=(now<<3)+(now<<1)+c-'0',c=getchar();
    18     return now;
    19 }
    20 
    21 bool cmp(Ques a,Ques b)
    22 {//左端点所在块为第一关键字,右端点为第二关键字 
    23     //if((a.l-1)/size+1 == (b.l-1)/size+1) return a.r < b.r;
    24     if(a.l/size == b.l/size) return a.r < b.r;
    25     return a.l/size < b.l/size;
    26 }
    27 
    28 inline void Add(int p)
    29 {
    30     ++Times[p];
    31     if(Times[p]==2)
    32       ++now;
    33 }
    34 inline void Subd(int p)
    35 {
    36     --Times[p];
    37     if(Times[p]==1)
    38       --now;
    39 }
    40 
    41 int main()
    42 {
    43     freopen("1flower.in","r",stdin);
    44     freopen("1flower.out","w",stdout);
    45     n=read();c=read();m=read();
    46     size=sqrt(n);
    47     for(int i=1;i<=n;i++)
    48       color[i]=read();
    49     for(int i=1;i<=m;i++)
    50       q[i].l=read(),q[i].r=read(),q[i].id=i;
    51     sort(q+1,q+1+m,cmp);
    52     for(int i=1,l=1,r=0;i<=m;i++)
    53     {
    54         int ln=q[i].l,rn=q[i].r;
    55         while(l>ln)
    56           Add(color[--l]);
    57         while(l<ln)
    58           Subd(color[l++]);
    59         while(r<rn)
    60           Add(color[++r]);
    61         while(r>rn)
    62           Subd(color[r--]);
    63         ans[q[i].id]=now;
    64     }
    65     for(int i=1;i<=m;i++)
    66       printf("%d
    ",ans[i]);
    67     fclose(stdin);fclose(stdout);
    68     return 0;
    69 }
    莫队

    2018.2.26 Update:

    +一些小优化

    时间:10.803s  内存使用:16.89MiB

     1 #include <cmath>
     2 #include <cctype>
     3 #include <cstdio>
     4 #include <algorithm>
     5 #define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
     6 const int N=1e6+5,MAXIN=1e6;
     7 
     8 int n,c,m,size,color[N],Times[N],now,ans[N];
     9 char IN[MAXIN],*SS=IN,*TT=IN;
    10 struct Ques
    11 {
    12     int l,r,id;
    13     bool operator <(const Ques &b)const{
    14         return l/size==b.l/size ? ((l/size)&1?r>b.r:r<b.r): l/size<b.l/size;
    15         //左端点所在块为第一关键字,右端点为第二关键字 
    16     }
    17 }q[N];
    18 
    19 inline int read()
    20 {
    21     int now=0;register char c=gc();
    22     for(;!isdigit(c);c=gc());
    23     for(;isdigit(c);now=now*10+c-'0',c=gc());
    24     return now;
    25 }
    26 inline void Add(int p){
    27     if(++Times[p]==2) ++now;
    28 }
    29 inline void Subd(int p){
    30     if(--Times[p]==1) --now;
    31 }
    32 
    33 int main()
    34 {
    35     freopen("1flower.in","r",stdin);
    36     freopen("1flower.out","w",stdout);
    37 
    38     n=read(),c=read(),m=read(),size=n/sqrt(m*2/3);
    39     for(int i=1;i<=n;i++) color[i]=read();
    40     for(int i=1;i<=m;i++) q[i].l=read(),q[i].r=read(),q[i].id=i;
    41     std::sort(q+1,q+1+m);
    42     for(int i=1,l=1,r=0;i<=m;i++)
    43     {
    44         int ln=q[i].l,rn=q[i].r;
    45         while(l>ln) Add(color[--l]);
    46         while(l<ln) Subd(color[l++]);
    47         while(r<rn) Add(color[++r]);
    48         while(r>rn) Subd(color[r--]);
    49         ans[q[i].id]=now;
    50     }
    51     for(int i=1;i<=m;i++) printf("%d
    ",ans[i]);
    52 
    53     fclose(stdin);fclose(stdout);
    54     return 0;
    55 }
    莫队2

    2.树状数组   时间:2.226s  内存使用:30.81MiB

     1 #include<cstdio>
     2 #include<algorithm>
     3 using namespace std;
     4 const int N=1000005;
     5 
     6 int n,c,m,color[N],Tree[N],Last[N],Next[N],Ans[N];
     7 struct Ques
     8 {
     9     int l,r,id;
    10     bool operator <(const Ques &a)const
    11     {
    12         return l<a.l;
    13     }
    14 }q[N];
    15 
    16 int read()
    17 {
    18     int now=0;char c=getchar();
    19     while(c<'0'||c>'9')c=getchar();
    20     while(c>='0'&&c<='9')now=(now<<3)+(now<<1)+c-'0',c=getchar();
    21     return now;
    22 }
    23 
    24 inline int lb(int x)
    25 {
    26     return x&(-x);
    27 }
    28 
    29 void Update(int p,int v)
    30 {
    31     while(p<=n)
    32       Tree[p]+=v,p+=lb(p);
    33 }
    34 
    35 int Query(int p)
    36 {
    37     int tmp=0;
    38     while(p)
    39       tmp+=Tree[p],p-=lb(p);
    40     return tmp;
    41 }
    42 
    43 int main()
    44 {
    45 //    freopen("1flower.in","r",stdin);
    46 //    freopen("1flower.out","w",stdout);
    47     n=read();c=read();m=read();
    48     for(int i=1;i<=n;i++)
    49       color[i]=read();
    50     for(int i=n;i>0;i--)
    51       Next[i]=Last[color[i]],Last[color[i]]=i;
    52     for(int i=1;i<=c;i++)
    53       if(Next[Last[i]])//颜色i第一个位置的下一个,即出现过2次,往后+1 
    54         Update(Next[Last[i]],1);
    55     for(int i=1;i<=m;i++)
    56       q[i].l=read(),q[i].r=read(),q[i].id=i;
    57     sort(q+1,q+1+m);
    58     for(int i=1,l=1;i<=m;i++)
    59     {
    60         while(l<q[i].l)
    61         {
    62             if(Next[l]) Update(Next[l],-1);//颜色i第一次出现的位置,往后-1(不算在内) 
    63             if(Next[Next[l]]) Update(Next[Next[l]],1);//颜色i第二次出现,往后+1 
    64             ++l;
    65         }
    66         Ans[q[i].id]=Query(q[i].r)-Query(q[i].l-1);
    67     }
    68     for(int i=1;i<=m;i++)
    69       printf("%d
    ",Ans[i]);
    70 //    fclose(stdin);fclose(stdout);
    71     return 0;
    72 }
    树状数组

    20分的暴力

     1 #include<cstdio>
     2 using namespace std;
     3 const int N=1000005;
     4 
     5 int n,c,m,Ans,color[N],Times[N];
     6 bool vis[N];
     7 
     8 int read()
     9 {
    10     int now=0;char c=getchar();
    11     while(c<'0'||c>'9')c=getchar();
    12     while(c>='0'&&c<='9')now=(now<<3)+(now<<1)+c-'0',c=getchar();
    13     return now;
    14 }
    15 
    16 int main()
    17 {
    18     freopen("1flower.in","r",stdin);
    19     freopen("1flower.out","w",stdout);
    20     n=read();c=read();m=read();
    21     for(int i=1;i<=n;i++)
    22       color[i]=read();
    23     for(int i=1;i<=m;i++)
    24     {
    25         for(int j=1;j<=n;j++)
    26           vis[j]=Times[j]=0;
    27         Ans=0;
    28         int l=read(),r=read();
    29         for(int j=l;j<=r;j++)
    30         {
    31             if(vis[color[j]])continue;
    32             ++Times[color[j]];
    33             if(Times[color[j]]>1)
    34               vis[color[j]]=1,++Ans;
    35         }
    36         printf("%d
    ",Ans);
    37     }
    38     fclose(stdin);fclose(stdout);
    39     return 0;
    40 }
    View Code
  • 相关阅读:
    OC中ARC forbids explicit message send of release错误
    OC中内存管理(转)
    [题解]数学期望_luogu_P1850_换教室
    [题解](单调队列)luogu_P2216_BZOJ_1047 理想的正方形
    [题解]luogu_AT1224_JOIOJI
    [题解]区间dp_luogu_P3147 262144
    [筆記]歐拉路
    [題解/狀壓dp]POJ_2411_Mondriaan's dream
    [題解]luogu_P1854 花店櫥窗佈置
    [題解]luogu_P1052 過河
  • 原文地址:https://www.cnblogs.com/SovietPower/p/6912955.html
Copyright © 2011-2022 走看看