dbclick —2923
思路:一道很水的题目,随便怎么搞(向两边扩展或O(n)预处理)。然而我偏偏太过于自信,O(n)预处理时最后一个区域的R忘补充了(一敲起水题来就管不住这双手…)。
strsub —2991
思路:一道十分有趣的dp,虽然dp很明显,但需要找到其中的规律,结果是要前缀和维护前缀和…(欺负我读书少…)卡了我超久,最后只写了O(n^2),没有用hash优化(O(n))。
paths —2954
思路:简化题意,就是判两条路径是否相交。而假设两条路径相交,那么以任意一条的任意端点为根,交点一定是另一条路径的两个端点的lca。
此时,就冒出了一个神奇的贪心(正确性玄乎),将lca的深度从大到小排序,每个路径经过就mark掉。
#include<bits/stdc++.h>
#define REP(i,f,t) for(int i=(f),i##_end_=(t);i<=i##_end_;i++)
#define DREP(i,f,t) for(int i=(f),i##_end_=(t);i>=i##_end_;i--)
#define N 100005
#define M 20
#define P 1000000007
#define INF 0x3f3f3f3f
#define LL long long
// LL mod
using namespace std;
int n,m;
int fa[M][N],dis[N];
bool mark[N];
vector<int>E[N];
struct node{
int f,dep,from,to;
bool operator<(const node & a)const{
return dep>a.dep;
}
}Q[N];
//struct P_list{
// int Ds,Dep,dep[N];
// struct Node{
// int L,R;
// bool operator<(const Node &a)const{
// return R<a.R;
// }
// }es[N];
// bool check(){
// int sum=0;
// REP(i,1,n)if(E[i].size()<2)Ds=i,sum++;
// return sum==2;
// }
// void dfs(int x,int f,int d){
// Dep=max(Dep,d);
// dep[x]=d;
// REP(i,0,E[x].size()-1){
// int y=E[x][i];
// if(y==f)continue;
// dfs(y,x,d+1);
// }
// }
// void solve(){
// Dep=0;
// dfs(Ds,0,1);
printf("Ds=%d Dep=%d\n",Ds,Dep);
// REP(i,1,m)
// es[i]=(Node){min(dep[Q[i].from],dep[Q[i].to]),max(dep[Q[i].from],dep[Q[i].to])};
// sort(es+1,es+1+m);
// int now=1,i=1,ans=0;
// while(now<=Dep){
// if(now<=es[i].L && es[i].R<=Dep)now=es[i].R,ans++;
// i++;
// if(i>m)break;
// }
// cout<<ans<<endl;
// }
//
//
//}p_list;
struct P100{
void dfs(int x,int f,int dep){
fa[0][x]=f,dis[x]=dep;
REP(i,0,E[x].size()-1){
int y=E[x][i];
if(y==f)continue;
dfs(y,x,dep+1);
}
}
void Up(int &x,int step){
REP(i,0,M-1)if(step&(1<<i))x=fa[i][x];
}
int Lca(int a,int b){
if(dis[a]>dis[b])swap(a,b);
Up(b,dis[b]-dis[a]);
if(a==b)return a;
DREP(i,M-1,0)
if(fa[i][a]!=fa[i][b])a=fa[i][a],b=fa[i][b];
return fa[0][a];
}
void Dfs(int x,int f){
if(mark[x])return;
mark[x]=1;
REP(i,0,E[x].size()-1){
int y=E[x][i];
if(y==f)continue;
Dfs(y,x);
}
}
void Init(){
dfs(1,0,1);
REP(j,1,M-1)
REP(i,1,n)fa[j][i]=fa[j-1][fa[j-1][i]];
REP(i,1,m){
int lca=Lca(Q[i].from,Q[i].to);
Q[i].f=lca,Q[i].dep=dis[lca];
}
sort(Q+1,Q+m+1);
}
void solve(){
Init();
int ans=0;
REP(i,1,m){
int f=Q[i].f,a=Q[i].from,b=Q[i].to;
if(mark[f]||mark[a]||mark[b])continue;
Dfs(f,fa[0][f]);
ans++;
}
cout<<ans<<endl;
}
}p100;
void Rd(){
scanf("%d %d",&n,&m);
REP(i,1,n-1){
int a,b;
scanf("%d%d",&a,&b);
E[a].push_back(b);
E[b].push_back(a);
}
REP(i,1,m)scanf("%d%d",&Q[i].from,&Q[i].to);
// if(p_list.check())p_list.solve();
// else p100.solve();
p100.solve();
}
int main(){
Rd();
return 0;
}
小结:
最近几场考得很不稳定,忽高忽低地,每次不是第1题没ac就是第2题暴力打错了,第3题不用说了,没爆0就可以了…
这说明这自己的思维很不严谨呀!确实,第1、2题经常是没对拍的,或者说有时候连暴力都不好写…这又体现自己的dfs、全排列还不行呀。