发一下牢骚和主题无关:

​​​​

擒贼先擒王,每次赛后总结CF的题,我都爱好先搞E题,而且E题一般是我最爱的数据结构题,搞起来特爽

E题:给你一棵树,求满意距离之和<=L 且 路径上的权值之和<= w的点对量数。。。

类似的目题:​​http://poj.org/problem?id=1741​

方法是点的分治,详细参考漆子超的论文,​​分治算法在树的路径中的应用​​,论文里头经已讲了很详细了

会了poj 1741的话,其实这道题就是多了一个制限,还是排序,扫描,不过在求的时候须要用树状组数维护一下,其实很简单,不过我还是调试了良久,,,,,代码力能与思维力能都须要精雕细琢啊。

在求一个二元组序列有多少对满意件条时卡了良久,看大神们都是加了一个0 0进去,我就是不想加,于是越写越烦,不是少算就是多算,最后冷静下来新重想了想,那还是先算成两倍的吧

我的那个calc函数略挫,,,,

poj 1741


#include<cstdio> #include<cstring> #include<vector> #include<algorithm> using namespace std; const int MAX_N = 100010; struct Edge{  int b , w;  Edge() {}  Edge(int b,int w): b(b),w(w){  } }; #define Tr(it,x) for(vector<Edge>::iterator it = x.begin(); it!=x.end();it++) vector<Edge> edge[MAX_N]; int N , K; int size[MAX_N]  ; int opt[MAX_N]; bool del[MAX_N] ; long long  Ans ; vector<int>  tnode; void Dfs(int u,int fa) {  tnode.push_back(u);  opt[u] = 0;  size[u] = 1;  Tr(it,edge[u])  {   int v = it->b;   if(!del[v] && v!=fa){    Dfs(v , u);    opt[u] = max(opt[u],size[v]);    size[u] += size[v];    }  } } int Find(int u) // find the centre of gravity {  Dfs(u,-1);  int who = -1 , mx = MAX_N;  for(vector<int>::iterator it = tnode.begin(); it != tnode.end(); it++)  {   opt[*it] = max(opt[*it],size[u]-size[*it]);   if(mx > opt[*it]) {    mx = opt[*it];    who = *it;   }  }  return who; } vector<int> all , ch[MAX_N]; void Get_dis(int u,int fa,int len,vector<int> &ch) {  ch.push_back(len);  all.push_back(len);  Tr(it,edge[u])  {   if(it->b!=fa && !del[it->b]) {    Get_dis(it->b,u,len+it->w,ch);   }  } } long long calc(vector<int> dist)  {   long long ans  = 0;  int pt = 0 , sz = dist.size();  sort(dist.begin(),dist.end());  for(int i = 0,j = sz - 1;i <= j;i++)   {   while(i <= j && dist[i] + dist[j] > K) {    j--;   }   if(i < j) ans += j - i;  }  return ans; } void Solve(int u) {  tnode.clear();  u = Find(u); // the gravity center   all.clear(); // all of the distances  int nch = 0; // count of sons   all.push_back(0);  Tr(it,edge[u])  {   ch[nch].clear();    if(!del[it->b]) Get_dis(it->b,u,it->w,ch[nch++]);  }   Ans += calc(all);  for(int i = 0; i < nch; i++)  Ans -= calc(ch[i]);    del[u] = true;  Tr(it,edge[u])   if(!del[it->b])  Solve(it->b); } int main() {  int a,b,w;  while(scanf("%d%d",&N,&K),N||K)  {    for(int i = 1; i <= N; i++) edge[i].clear(),del[i]=false;          for(int i = 1; i < N; i++)    {     scanf("%d%d%d",&a,&b,&w);     edge[a].push_back(Edge(b,w));     edge[b].push_back(Edge(a,w));    }    Ans = 0;    Solve(1);    printf("%I64d\n",Ans);  }  return 0; }

每日一道理

生活中受伤难免,失败跌倒并不可怕,可怕的是因此而一蹶不振,失去了对人生的追求与远大的理想。没有一个人的前进道路是平平稳稳的,就算是河中穿梭航行的船只也难免颠簸,生活中所遇上的坎坷磨难不是偶尔给予的为难,而是必然所经受的磨练。


CROC round2 E

// http://poj.org/problem?id=1741 #include<cstdio> #include<cstring> #include<vector> #include<algorithm> using namespace std; const int MAX_N = 100010; struct Edge{  int b , w;  Edge() {}  Edge(int b,int w): b(b),w(w){  } }; #define Tr(it,x) for(vector<Edge>::iterator it = x.begin(); it!=x.end();it++) vector<Edge> edge[MAX_N]; int N , K; int size[MAX_N]  ; int opt[MAX_N]; bool del[MAX_N] ; long long  Ans ; vector<int>  tnode; void Dfs(int u,int fa) {  tnode.push_back(u);  opt[u] = 0;  size[u] = 1;  Tr(it,edge[u])  {   int v = it->b;   if(!del[v] && v!=fa){    Dfs(v , u);    opt[u] = max(opt[u],size[v]);    size[u] += size[v];    }  } } int Find(int u) // find the centre of gravity {  Dfs(u,-1);  int who = -1 , mx = MAX_N;  for(vector<int>::iterator it = tnode.begin(); it != tnode.end(); it++)  {   opt[*it] = max(opt[*it],size[u]-size[*it]);   if(mx > opt[*it]) {    mx = opt[*it];    who = *it;   }  }  return who; } vector<pair<int,int> > all , ch[MAX_N]; void Get_dis(int u,int fa,int len,vector<pair<int,int> > &ch,int sum) {  ch.push_back(make_pair(sum,len));  all.push_back(make_pair(sum,len));  Tr(it,edge[u])  {   if(it->b!=fa && !del[it->b]) {    Get_dis(it->b,u,len+it->w,ch,sum+1);   }  } } struct BIT{  int c[MAX_N];  int maxn ;  void init(int n) {   maxn = n;   memset(c,0,sizeof(int)*n);  }  void insert(int x,int d) {   for(x++;x<=maxn;x+=x&-x) c[x] += d;  }  int sum(int x) {   int ans = 0;   for(x++;x;x-=x&-x) ans += c[x];   return ans;  } }bit; int L , W; int cmp(pair<int,int> a, pair<int,int> b) {  if(a.second != b.second)return a.second < b.second;  return a.first < b.first; } long long calc(vector<pair<int,int> > d,bool f) //这个函数写挫了,囧 {   long long ans  = 0;  int pt = 0 , sz = d.size();  int mxd = 0;  for(int i = 0; i < sz ; i++) {   mxd = max(mxd,d[i].first);  }  bit.init(mxd+2);  sort(d.begin(),d.end(),cmp);  int cnt = 0;  int j = 0;  for(int i = sz - 1 ; i >= 0; i--) {// cnt : 单个点到根满意件条的个数,独单计统出来   if(f && d[i].first <= L && d[i].second <= W) cnt++;   while(j < sz && d[j].second + d[i].second <= W) {    bit.insert(d[j].first,1);    j++;   }      if(L >= d[i].first){    ans += bit.sum(min(mxd,L-d[i].first));    if(j > i) if(d[i].first+d[i].first <= L) ans --; // 自己 与 自己不能算点对,要去掉   }  }  ans += cnt * 2;  return ans; } void Solve(int u) {  tnode.clear();  u = Find(u); // the gravity center   all.clear(); // all of the distances  int nch = 0; // count of sons   Tr(it,edge[u])  {   ch[nch].clear();    if(!del[it->b]) Get_dis(it->b,u,it->w,ch[nch++],1);  }    Ans += calc(all,true);  for(int i = 0; i < nch; i++)  Ans -= calc(ch[i],false);    del[u] = true;  Tr(it,edge[u])   if(!del[it->b])  Solve(it->b); } int main() {  int a,b,w;  while(scanf("%d%d%d",&N,&L,&W)!=EOF)  {    for(int i = 1; i <= N; i++) edge[i].clear(),del[i]=false;          for(int i = 2; i <= N; i++)    {     scanf("%d%d",&a,&w);     edge[i].push_back(Edge(a,w));     edge[a].push_back(Edge(i,w));    }    Ans = 0;    Solve(1);    printf("%I64d\n",Ans/2);  }  return 0; }

文章结束给大家分享下程序员的一些笑话语录: 很多所谓的牛人也不过如此,离开了你,微软还是微软,Google还是Google,苹果还是苹果,暴雪还是暴雪,而这些牛人离开了公司,自己什么都不是。