2017.8.13 改题

考完今天的试,充分说明了 对于简单题对拍的重要性  另外对于树的数据生成器,用并查集,但是我想也可以用一遍dfs

T1

给一个n长度的序列,只能修改其中一个数到任意整数(也可以不修改),求最长严格上升子串

solution

先O(n)求出原序列中所有上升子串,枚举每一个点作为要修改的点

分修改后 能把几个序列合并 还是 在原来长度上+1

(挂的原因:少写了一个-1,这个错误对拍一定能拍出来)

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #define ll long long
  5 #define mem(a,b) memset(a,b,sizeof(a))
  6 using namespace std;
  7 const int INF=(1<<31)-1;
  8 const int N=300006;
  9 int read()
 10 {
 11     int ans=0,flag=1;char q=getchar();
 12     while(q<'0'||q>'9'){if(q=='-')flag=-1;q=getchar();}
 13     while(q>='0'&&q<='9'){ans=ans*10+q-'0';q=getchar();}
 14     return ans;
 15 }
 16 
 17 int n,ans;
 18 int a[N];
 19 int L[N],R[N],cnt,len[N];
 20 
 21 void hh()
 22 {
 23     int temp;
 24     for(int i=1;i<=cnt;++i)
 25       if(ans<len[i])
 26         ans=len[i];
 27     
 28     if(cnt==1)return ;
 29     
 30     if(len[1]==1)
 31     {
 32         temp=len[2]+1;
 33         if(ans<temp)
 34           ans=temp;
 35     }
 36     else
 37     {
 38         if(a[R[1]-1]+1<a[R[1]+1])
 39         {
 40             temp=len[1]+len[2];
 41             if(ans<temp)
 42               ans=temp;
 43         }
 44         else
 45         {
 46             temp=len[2]+1;
 47             if(ans<temp)
 48               ans=temp;
 49         }
 50     }
 51     
 52     for(int i=2;i<cnt;++i)
 53     {
 54         if(len[i]==1)
 55         {
 56             if(a[L[i]-1]+1<a[L[i]+1])
 57             {
 58                 temp=len[i-1]+len[i]+len[i+1];
 59                 if(ans<temp)
 60                   ans=temp;
 61             }
 62             else
 63             {
 64                 temp=len[i-1]+1;
 65                 if(ans<temp)
 66                   ans=temp;
 67                 temp=len[i+1]+1;
 68                 if(ans<temp)
 69                   ans=temp;
 70             }
 71         }
 72         else
 73         {
 74             if(a[L[i]-1]+1<a[L[i]+1])
 75             {
 76                 temp=len[i-1]+len[i];
 77                 if(ans<temp)
 78                   ans=temp;
 79             }
 80             else
 81             {
 82                 temp=len[i-1]+1;
 83                 if(ans<temp)
 84                   ans=temp;
 85             }
 86             
 87             if(a[R[i]-1]+1<a[R[i]+1])//a[R[i]-1]+1<a[R[i]+1]  写成了  a[R[i]]+1<a[R[i]+1] 
 88             {
 89                 temp=len[i]+len[i+1];
 90                 if(ans<temp)
 91                   ans=temp;
 92             }
 93             else
 94             {
 95                 temp=len[i+1]+1;
 96                 if(ans<temp)
 97                   ans=temp;
 98             }
 99         }
100     }
101     
102     if(len[cnt]==1)
103     {
104         temp=len[cnt-1]+1;
105         if(ans<temp)
106           ans=temp;
107     }
108     else
109     {
110       if(a[L[cnt]-1]+1<a[L[cnt]+1])
111       {
112             temp=len[cnt-1]+len[cnt];
113             if(ans<temp)
114               ans=temp;
115         }
116         else
117         {
118             temp=len[cnt-1]+1;
119             if(ans<temp)
120               ans=temp;
121         }
122     }
123 }
124 
125 int main(){
126     
127     //freopen("lis8.in","r",stdin);
128     
129     n=read();
130     for(int i=1;i<=n;++i)
131       a[i]=read();
132     
133     for(int i=1;i<=n;++i)
134     {
135         int now=i;
136         while(now<n&&a[now+1]>a[now])
137           ++now;
138         L[++cnt]=i;
139         R[cnt]=now;
140         len[cnt]=R[cnt]-L[cnt]+1;
141         i=now;
142     }
143     
144     /*printf("\n");
145     for(int i=1;i<=cnt;++i)
146       printf("%d %d\n",L[i],R[i]);
147     printf("\n");*/
148     
149     hh();
150     cout<<ans;
151     //while(1);
152     return 0;
153 }
T1

T2  中值滤波

给一个长为n的01序列,每次进行一次操作使 a[] → b[]

规则:  b[1]=a[1]  b[n]=a[1]   b[i]={a[i-1],a[i],a[i+1]}中位数

输出  最少几步之后"稳定",无解输出 -1

solution

首先不可能无解,因为两端已经确定

之(da)后(biao)发现连续两个以上的0/1不会在变,并且0 1交替的串从两边向中间趋于稳定,然后找规律就行了

(这个是因为 打表打错了......这个也可以拍出来嘛 )

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #define ll long long
 5 #define mem(a,b) memset(a,b,sizeof(a))
 6 using namespace std;
 7 const int INF=(1<<31)-1;
 8 const int N=500006;
 9 int read()
10 {
11     int ans=0,flag=1;char q=getchar();
12     while(q<'0'||q>'9'){if(q=='-')flag=-1;q=getchar();}
13     while(q>='0'&&q<='9'){ans=ans*10+q-'0';q=getchar();}
14     return ans;
15 }
16 
17 int n,a[N],f[N],num,ans;
18 int L[N],R[N],cnt,co[N];
19 
20 int main(){
21     
22 ///    freopen("median4.in","r",stdin);
23     
24     n=read();
25     for(int i=1;i<=n;++i)
26       a[i]=read();
27     a[0]=a[1];a[n+1]=a[n];
28     
29     for(int i=0;i<=n+1;++i)
30     {
31         int now=i;
32         while(now<n+1&&a[now+1]==a[now])
33           ++now;
34         if(now==i)
35           continue;
36         L[++cnt]=i;
37         R[cnt]=now;
38         co[cnt]=a[i];
39         i=now;
40     }
41     
42     int temp;
43     for(int i=1;i<cnt;++i)
44     {
45         if(co[i]==co[i+1])
46         {
47             for(int j=R[i]+1;j<L[i+1];++j)
48               a[j]=co[i];
49             temp=(L[i+1]-R[i]-1-1)/2;
50             if(temp==0)
51             {
52                 if(ans<1)
53                   ans=1;
54             }
55             else
56                 if(temp&1)
57                 {
58                     if(ans<temp+1)
59                       ans=temp+1;
60                 }
61                 else
62                 {
63                     if(ans<temp+1)
64                       ans=temp+1;
65                 }
66         }
67         else
68         {
69             temp=(L[i+1]-R[i]-1)/2;
70             for(int j=R[i]+1;j<=R[i]+temp;++j)
71               a[j]=co[i];
72             for(int j=L[i+1]-temp;j<L[i+1];++j)
73               a[j]=co[i+1];
74             if(ans<temp)
75               ans=temp;
76         }
77     }
78     
79     printf("%d\n",ans);
80     for(int i=1;i<=n;++i)
81       printf("%d ",a[i]);
82     
83 //    while(1);
84     return 0;
85 }
T2

T3  约会

给一个n个点 n-1条边的树,m次询问 到x和y距离相等的点有几个

solution

先求出x→y路径长度len,如果len&1,那就无解

在求出路径上的中点,如果是LCA,那 ans=(n-size[LCA])+size[son[LCA]](son!=x/y到LCA路径上的点)

如果不是LCA ans=size[son[LCA']]  (son!=fa[LCA']/x/y到LCA'路径上的点)

(忠告:不要用树链剖分,树上倍增大法好!!!)

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<iostream>
  4 #define mem(a,b) memset(a,b,sizeof(a))
  5 using namespace std;
  6 const int N=100006;
  7 struct son
  8 {
  9     int v,next;
 10 };
 11 son a1[N*5];
 12 int first[N*5],e;
 13 void addbian(int u,int v)
 14 {
 15     a1[e].v=v;
 16     a1[e].next=first[u];
 17     first[u]=e++;
 18 }
 19 
 20 int n,u,o,m;
 21 int fa[N],dep[N],q[N][33],size[N];
 22 
 23 void dfs1(int x)
 24 {
 25     size[x]=1;
 26     for(int i=first[x];i!=-1;i=a1[i].next)
 27     {
 28         int temp=a1[i].v;
 29         if(temp==fa[x])continue;
 30         dep[temp]=dep[x]+1;
 31         fa[temp]=x;
 32         dfs1(temp);
 33         size[x]+=size[temp];
 34     }
 35 }
 36 
 37 void chu()
 38 {
 39     mem(q,-1);
 40     for(int i=0;i<=n;++i)//点的编号有0 
 41       q[i][0]=fa[i];
 42     for(int j=1;(1<<j)<=n;++j)
 43       for(int i=0;i<=n;++i)
 44         if(q[i][j-1]!=-1)
 45           q[i][j]=q[q[i][j-1]][j-1];
 46 }
 47 
 48 int LCA(int x,int y)
 49 {
 50     if(dep[x]<dep[y])
 51       swap(x,y);
 52     int tx=x,ty=y,lca,dx=0,dy=0,ans=0;//lca是假的lca,其实是中点 
 53     int num=0;
 54     while((1<<num)<=dep[x])++num;
 55     for(int j=num;j>=0;--j)
 56       if(dep[x]-(1<<j)>=dep[y])
 57       {
 58         x=q[x][j];
 59         dx+=(1<<j);
 60         }
 61     
 62     //printf("1\n");
 63     
 64     if(x==y)
 65     {
 66         if(dx&1)
 67           return 0;
 68         dx>>=1;
 69         --dx;//***
 70       x=tx;
 71       for(int j=num;j>=0;--j)
 72         if((1<<j)<=dx)
 73         {
 74                 x=q[x][j];
 75           dx-=(1<<j);
 76             }
 77       lca=fa[x];
 78       for(int i=first[lca];i!=-1;i=a1[i].next)
 79       {
 80             int temp=a1[i].v;
 81             if(temp==fa[lca]||temp==x)continue;
 82             ans+=size[temp];
 83         }
 84         return ans+1;
 85     }
 86     
 87     //printf("2\n");
 88     
 89     for(int j=num;j>=0;--j)
 90       if(q[x][j]!=-1&&q[x][j]!=q[y][j])
 91       {
 92             x=q[x][j];dx+=(1<<j);
 93             y=q[y][j];dy+=(1<<j);
 94         }
 95     ++dx;++dy;
 96     if((dx+dy)&1)
 97       return 0;
 98     
 99     //printf("4\n");
100     
101     if(dx==dy)
102     {
103         lca=fa[x];
104         //printf("lca=%d x=%d y=%d\n",lca,x,y);
105         for(int i=first[lca];i!=-1;i=a1[i].next)
106         {
107             int temp=a1[i].v;
108             if(temp==fa[lca]||temp==x||temp==y)continue;
109             ans+=size[temp];
110         }
111         ++ans;
112         ans+=(n-size[lca]);
113         return ans;
114     }
115     
116     //printf("3\n");
117     
118     int val=(dx+dy)>>1;
119     --val;//***
120     x=tx;
121     for(int j=num;j>=0;--j)
122       if((1<<j)<=val)
123       {
124         x=q[x][j];
125         val-=(1<<j);
126         }
127     lca=fa[x];
128     for(int i=first[lca];i!=-1;i=a1[i].next)
129     {
130         int temp=a1[i].v;
131         if(temp==fa[lca]||temp==x)continue;
132         ans+=size[temp];
133     }
134     return ans+1;
135 }
136     
137 
138 int main(){
139     
140     //freopen("1.txt","r",stdin);
141     
142     //freopen("date.in","r",stdin);
143     //freopen("date.out","w",stdout);
144     //freopen("2.txt","w",stdout);
145     
146     mem(first,-1);
147     mem(fa,-1);
148     
149     scanf("%d",&n);
150     for(int i=1;i<n;++i)
151     {
152         scanf("%d%d",&u,&o);
153         addbian(u,o);
154         addbian(o,u);
155     }
156     
157     dfs1(2);//我用1不行..... 
158     chu();
159     
160     scanf("%d",&m);
161     for(int i=1;i<=m;++i)
162     {
163         //printf("i=%d\n",i);
164         scanf("%d%d",&u,&o);
165         if(u==o)
166           printf("%d\n",n);//竟然有重的
167         else
168             printf("%d\n",LCA(u,o));
169     }
170     
171     //while(1);
172     return 0;
173 }
T3

总结

1.对于简单题,一定要打对拍,不然会死的很惨

2.还有就是不要太关注平时考试成绩,要注重于学习时的专注、思考与坚持

3.如果你看到一个题数据范围不正常的小,肯定跟正解有关系

posted @ 2017-08-13 15:57  A_LEAF  阅读(161)  评论(0编辑  收藏  举报