好题。。写了两个半小时hh,省选的时候要一个半小时内调出这种题目还真是难= =

题目大意是给一棵树或环套树,求点距大于等于K的点对数

这里的树状数组做了一点变换。不是向上更新和向下求和,而是反过来,所以求和的时候sum(k)实际上是求k到n的和

所以我们要求大于等于k的dis的次数和,就是求sum(1,k-1),注意k要减一

如果是树,就是常规的点分治,然后用树状数组维护dis【t】出现的次数

如果是环套树,找环之后割掉一条边,然后先求这棵树的答案。接着考虑过了这条割掉的边s--t的情况:我们以这条边的一点t为起点,对于环上的每个点(即每棵子树的根),我们求出这棵子树的所有dis后,dis+cir_len-i为所求链的第一部分,链的第二部分的长度为k-(dis+cir_len-i),用树状数组求就可以了。更新树状数组的时候不是更新dis,而是dis+i;i即根到割的那条边的另一个点s的距离&&这条割边

完美解决。。然而常数还是很大,跑了两秒多

 #include<stdio.h>
 #include<string.h>
 #include<algorithm>
 #define INF 0x3f3f3f3f
 #define LL long long
 using namespace std;
 ;
 struct node{
     int to,next;
 }e[maxn*];
 int n,m,K,head[maxn],size[maxn],vis[maxn],sz,total,root,dis[maxn],tot,fa[maxn];
 ;
 LL p[maxn*],ans;

 void insert(int u, int v){
     e[++tot].to=v; e[tot].next=head[u]; head[u]=tot;
 }

 void add(int x, LL c){
     for (;x;x-=x&-x) p[x]+=c;
 }
 LL query(int x){  //注意:这里的树状数组是倒过来的, query(1,k) 是求得k+1到n
     LL ret=;
     ) x=;
     *n;x+=x&-x) ret+=p[x];
     return ret;
 }

 void getroot(int u, int f){
     size[u]=; ;
     for (int v,i=head[u]; i; i=e[i].next){
         if (vis[v=e[i].to] || v==f || i==ban1 || i==ban2) continue;
         getroot(v,u);
         size[u]+=size[v];
         mx=max(mx,size[v]);
     }
     mx=max(mx,total-size[u]);
     if (mx<sz) sz=mx,root=u;
 }

 void getdis(int u, int f, int d){
     dis[++tot]=d;
     for (int i=head[u],v; i; i=e[i].next){
         if (vis[v=e[i].to] || v==f || i==ban1 || i==ban2) continue;
         getdis(v,u,d+);
     }
 }

 void work(int u){
     total=size[u]?size[u]:n;
     sz=INF;
     getroot(u,); u=root;
     vis[u]=; tot=;
     ; i; i=e[i].next){
         if (vis[v=e[i].to] || i==ban1 || i==ban2) continue;
         last=tot;
         getdis(v,,); //printf("%d\n", tot);
         ; j<=tot; j++) ans+=query(K--dis[j]);
         ; j<=tot; j++) add(dis[j],);
     }
     ans+=query(K-);
     );
     for (int v,i=head[u]; i; i=e[i].next)
         if (!vis[v=e[i].to] && i!=ban1 && i!=ban2) work(v);
 }

 void find_cir(int u, int f){
     vis[u]=; if (len) return;//printf("  %d\n", u);
     for (int i=head[u],v; i; i=e[i].next){
         v=e[i].to;
         if (v==f || len) continue;
         fa[v]=u;// printf("now %d\n", u);
         if (vis[v]){
             ban1=i; ban2=i^;
             for (int x=fa[v]; x!=v; x=fa[x]) cir[++len]=x; cir[++len]=v;
             return;
         }
         find_cir(v,u);
     }
 }

 void cut(){
     ; i<=n; i++) vis[i]=;
     work();// printf("  %lld\n", ans);
     ; i<=n; i++) p[i]=0LL,vis[i]=;
     ; i<=len; i++) vis[cir[i]]=;
     ; i<=len; i++){
         ;
         getdis(u,,); //printf("  %d\n", tot);
         ; j<=tot; j++) ans+=query(K-dis[j]-(len-i+));//, printf("%lld\n", ans);
         );
     }
 }

 int main(){
     scanf(;
     ,u,v; i<=m; i++){
         scanf("%d%d", &u, &v);
         insert(u,v); insert(v,u);
     }
     ) work();
     else{
         find_cir(,);
         cut();
     }
     printf("%lld\n", ans);
     ;
 } 

bzoj3648: 寝室管理(环套树+点分治)的更多相关文章

  1. 【BZOJ-3648】寝室管理 环套树 + 树状数组 + 点分治

    3648: 寝室管理 Time Limit: 40 Sec  Memory Limit: 512 MBSubmit: 239  Solved: 106[Submit][Status][Discuss] ...

  2. BZOJ3648 寝室管理 【点分治 + 环套树】

    3648: 寝室管理 Time Limit: 40 Sec  Memory Limit: 512 MB Submit: 366  Solved: 152 [Submit][Status][Discus ...

  3. BZOJ3648 : 寝室管理

    求环套外向树上节点数不小于K的路径数. 首先树的话直接点分治+树状数组$O(n\log^2n)$搞定 环套树的话,先删掉多余的边(a,b) 然后变成了一棵树,直接点分治 然后在树上找到a到b的路径,将 ...

  4. 【bzoj3648】环套树+点分治+树状数组

    tree 1s 128M  by hzw czy神犇种了一棵树,他想知道地球的质量 给定一棵n个点的树,求树上经过点的个数≥K的路径数量ans 对于部分数据,树上某两点间会多出最多一条无向边 输入数据 ...

  5. 【BZOJ3648】寝室管理 树分治

    [BZOJ3648]寝室管理 Description T64有一个好朋友,叫T128.T128是寄宿生,并且最近被老师叫过去当宿管了.宿管可不是一件很好做的工作,碰巧T128有一个工作上的问题想请T6 ...

  6. BZOJ 3648: 寝室管理( 点分治 + 树状数组 )

    1棵树的话, 点分治+你喜欢的数据结构(树状数组/线段树/平衡树)就可以秒掉, O(N log^2 N). 假如是环套树, 先去掉环上1条边, 然后O(N log^2 N)处理树(同上); 然后再O( ...

  7. [ARC083F] Collecting Balls [建二分图+环套树定向+建拓扑图+树的拓扑序计数]

    题面 [传送门](https://arc083.contest.atcoder.jp/tasks/arc083_d) 思路 这是一道真正的好题 第一步:转化模型 行列支配类的问题,常见做法就是把行和列 ...

  8. 【BZOJ-1040】骑士 树形DP + 环套树 + DFS

    1040: [ZJOI2008]骑士 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 3312  Solved: 1269[Submit][Status ...

  9. 【BZOJ】1040: [ZJOI2008]骑士(环套树dp)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1040 简直不能再神的题orz. 蒟蒻即使蒟蒻,完全不会. 一开始看到数据n<=1000000就 ...

随机推荐

  1. ajax 设置同步

    这个问题总是碰见,但是又总是记不住怎么拼写,这次直接写出来,长期保存. Ajax请求默认的都是异步的 如果想同步 async设置为false就可以(默认是true) 例如: $.ajax({      ...

  2. 还敢说你是程序员?一律师闲着没事写了个app,用户量600万

    今天周五,是我在上海上班的第五天. 这几天怎么说呢,跟混日子差不多,因为处处有“”惊喜”. 上班第一天领来办公电脑,登上自己的公司邮箱,惊喜来了!我的擦擦擦,全TM是英文呐!作为一个从村儿里来的码农, ...

  3. 关于chart.js 设置canvas的宽度为父级元素的宽度的百分百 以及 X轴上面刻度数据太多如何处理

    今天在做一个数据统计的界面的时候,需要做折线统计图,在网上找了一圈发现数据统计的插件还是不少的,本着轻量级的的原则选择了Chart.js,后来在做的过程中便遇到两个问题,以此记录下来,和刚刚接触前端的 ...

  4. .net MVC 简单图片上传

    主要完成的是在网页上 上传一张图片到服务器 我搜出来的上传文件代码都特别复杂,对于初学者来说,先解决能上传的问题才最重要,并不需要特别多的功能,仅适合不会上传的初学者,大神请绕路,错误请指出,谢谢 v ...

  5. cron(CronTrigger)表达式用法

    CronTrigger CronTriggers往往比SimpleTrigger更有用,如果您需要基于日历的概念,而非SimpleTrigger完全指定的时间间隔,复发的发射工作的时间表.CronTr ...

  6. centos安装tmux过程

    原文:https://gist.github.com/rothgar/cecfbd74597cc35a6018 # Install tmux on Centos release 6.5 # insta ...

  7. Centos7 关闭防火墙(转)

    转载地址:http://www.cnblogs.com/silent2012/archive/2015/07/28/4682770.html CentOS 7.0默认使用的是firewall作为防火墙 ...

  8. PROC 文件系统调节参数介绍(netstat -us)

    转自:http://www.cnblogs.com/super-king/p/3296333.html /proc/net/* snmp文件 Ip: ip项 Forwarding        : 是 ...

  9. QT生成流水账号

    在做数据库课程的时候,要生成财务表,每条记录应该有一个流水账号. 实现思路: 当前时间+随机一个四位数 上代码 //生成流水号 QString adminRecharge::getNumber() { ...

  10. Tomcat的粗略介绍

    因为工作的缘故很多项目启动需要通过Tomcat修改配置文件进行启动项目,所以相应的就了解了下Tomcat便于在以后比我更新的新人面前装逼. 1.bin目录 我们能用到的无非一个启动跟一个关闭没什么好说 ...