2017.10.9离线赛总结

来源:互联网 发布:古筝软件下载手机 编辑:程序博客网 时间:2024/06/04 20:12

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、全排列还不行呀。

原创粉丝点击