博客园 首页 私信博主 显示目录 隐藏目录 管理 动画

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\n",cnt,cur);
33     for(int i=H[cur];i;i=e[i].nxt)
34     {
35         int to=e[i].to;//printf("%d OK\n",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\n",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\n",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\n",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\n",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\n",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\n",Blo[n]);
49 //    for(int i=1;i<=Blo[n];i++)
50 //      printf("%d:All:%d\n",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\n",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\n",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\n",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\n",Ans);
37     }
38     fclose(stdin);fclose(stdout);
39     return 0;
40 }
View Code

 

posted @ 2017-05-27 15:07  SovietPower  阅读(226)  评论(4编辑  收藏  举报