题目

这题的数据有点水,暴力合并\(set\)好像过了

分析一下这个题的性质,发现我们一条非树边就会形成一个环,而我们要求选择两个非树边,就会形成两个环,要求不走重复的点,就是说我们需要走一个大环,且必须经过这两个小环

显然需要这两个小环有至少一条公共边

发现问题转化成了求有多少对路径,这对路径有公共边

应该可以用数据结构来维护大力讨论的,当然树上差分的正解思路也非常妙

于是我们写个暴力吧!

对于这道题我第一想法是启发式合并\(set\),我们可以利用如同树上差分那样的方式,对于一条路径\((u,v)\),我们在\(u,v\)处打上一个标记,在\(lca(u,v)\)再打上一个删除标记,每次合并\(set\)的时候,往\(set\)里插入的所有标记都表明这个标记代表的路径经过了这条边,这样这条路径就可以和原来\(set\)里的标记任意组合了,就可以统计答案了

但是会和正解树上差分遇到一样的问题,就是如果两条路径的公共边形成的不是一条链,这对路径我们会计算两次

这里采用和正解一样的方法就好了,就是利用一个\(map\)来找到这样的路径有多少对

到这里复杂度还非常正常,是有点大的\(O(nlog^2n)\),但是我们又发现我们好像没有什么办法去利用删除标记

如果每次合并前都要扫一遍删除集合的话,复杂度显然就不对了,菊花树随便卡掉

于是我们启发式删除,看看维护删除集合小还是待合并集合小,那个小就遍历哪一个

还是过不去怎么办,那就把\(set\)换成unordered_set,信仰一下就可以了

代码

#include<tr1/unordered_set>
#include<tr1/unordered_map>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#define maxn 200005
#define re register
#define LL long long
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define set_it unordered_set<int>::iterator
# define getchar() (S==T&&(T=(S=BB)+fread(BB,1,1<<15,stdin),S==T)?EOF:*S++)
using namespace std::tr1;
char BB[1 << 18],*S=BB,*T=BB;
inline int read() {
int x=0;char c=getchar();while(c<'0'||c>'9') c=getchar();
while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
}
struct E{int v,nxt;}e[maxn<<1];
int head[maxn],deep[maxn],sum[maxn],fa[maxn],top[maxn],son[maxn],f[maxn][19],st[maxn];
int n,m,num,cnt,md,t;
int rt[maxn];
LL ans;
unordered_set<int> s[maxn],del[maxn];
unordered_map<LL,int> ma;
inline void add(int x,int y) {e[++num].v=y;e[num].nxt=head[x];head[x]=num;}
void dfs1(int x) {
sum[x]=1;int maxx=-1;
for(re int i=head[x];i;i=e[i].nxt) {
if(deep[e[i].v]) continue;
deep[e[i].v]=deep[x]+1;fa[e[i].v]=x;f[e[i].v][0]=x;
for(re int j=1;j<=18;j++) f[e[i].v][j]=f[f[e[i].v][j-1]][j-1];
dfs1(e[i].v);
sum[x]+=sum[e[i].v];
if(sum[e[i].v]>maxx) maxx=sum[e[i].v],son[x]=e[i].v;
}
}
void dfs2(int x,int topf) {
top[x]=topf;
if(!son[x]) return;
dfs2(son[x],topf);
for(re int i=head[x];i;i=e[i].nxt) {
if(top[e[i].v]) continue;
dfs2(e[i].v,e[i].v);
}
}
inline int LCA(int x,int y) {
while(top[x]!=top[y]) {
if(deep[top[x]]<deep[top[y]]) std::swap(x,y);
x=fa[top[x]];
}
if(deep[x]<deep[y]) return x;return y;
}
inline void D(int a,int c) {
if(del[c].size()<s[a].size()) {
for(set_it it=del[c].begin();it!=del[c].end();++it) {
int x=*it;
s[a].erase(x);
}
return;
}
t=0;
for(set_it it=s[a].begin();it!=s[a].end();++it)
if(del[c].find(*it)!=del[c].end()) st[++t]=*it;
while(t) s[a].erase(st[t--]);
}
inline void merge(int a,int b,int c) {
int now=s[a].size();
for(set_it it=s[b].begin();it!=s[b].end();++it) {
int x=*it;
if(del[c].find(x)!=del[c].end()) continue;
ans+=now;s[a].insert(x);
}
}
inline int jump(int x,int y) {
for (re int i=18;i>=0;--i) if(deep[x]-(1<<i)>deep[y]) x=f[x][i];
return x;
}
void dfs(int x) {
D(rt[x],x);
for(re int i=head[x];i;i=e[i].nxt) {
if(deep[e[i].v]<deep[x]) continue;
dfs(e[i].v);
if(s[rt[e[i].v]].size()<=s[rt[x]].size()) {
if(x!=1) merge(rt[x],rt[e[i].v],x);
}
else {
D(rt[e[i].v],x);
if(x!=1) merge(rt[e[i].v],rt[x],x),rt[x]=rt[e[i].v];
}
}
}
int main() {
n=read(),m=read();int x,y,z;
for(re int i=1;i<n;i++) x=read(),y=read(),add(x,y),add(y,x);
deep[1]=1,dfs1(1),dfs2(1,1);
for(re int i=1;i<=n;i++) rt[i]=i;
for(re int i=n;i<=m;i++) {
x=read(),y=read();z=LCA(x,y);
if(x==y) continue;
if(deep[x]<deep[y]) std::swap(x,y);
ans+=s[x].size();
if(z!=y) ans+=s[y].size();
s[x].insert(i);
if(z!=y) s[y].insert(i);
del[z].insert(i);
if(x==z||y==z) continue;
int xx=jump(x,z),yy=jump(y,z);
if(xx>yy) std::swap(xx,yy);
ans-=ma[(LL)xx*(LL)n+yy];ma[(LL)xx*(LL)n+yy]++;
}
dfs(1);
printf("%lld\n",ans);
}

[USACO19JAN]Exercise Route的更多相关文章

  1. [USACO19JAN]Exercise Route P

    先让我们探索一下两条非树边以及树边能构成简单环的条件是什么,你会发现将第一条非树边的两个点在树上形成的链记为 \(W_1\),另一条即为 \(W_2\),那么当且仅当 \(W_1, W_2\) 有交时 ...

  2. [USACO18DEC]The Cow Gathering P

    首先可以思考一下每次能删去的点有什么性质. 不难发现,每次能删去的点都是入度恰好为 \(1\) 的那些点(包括 \(a_i \rightarrow b_i\) 的有向边). 换句话说,每次能删去的点既 ...

  3. Application Request Route实现IIS Server Farms集群负载详解

    序言 随着公司业务的发展,后台业务就变的越来越多,然而服务器的故障又像月经一样,时不时的汹涌而至,让我们防不胜防.那么后台的高可用,以及服务器的处理能力就要做一个横向扩展的方案,以使后台业务持续的稳定 ...

  4. .net core 源码解析-mvc route的注册,激活,调用流程(三)

    .net core mvc route的注册,激活,调用流程 mvc的入口是route,当前请求的url匹配到合适的route之后,mvc根据route所指定的controller和action激活c ...

  5. angular路由——ui.route

    angular路由 使用案例 <!DOCTYPE html> <html lang="en"> <head> <meta charset= ...

  6. 如何在ARM中创建Express Route

    很早之前就想试试Azure的express route,但是一直没有找到合适的机会,正好有个客户需要上express route,所以最近先自己研究研究,防止在做poc的时候耗费更多时间,本次场景我们 ...

  7. Python flask @app.route

    转载自 http://python.jobbole.com/80956/ 下面是Flask主页给我们的第一个例子,我们现在就由它入手,深入理解“@app.route()”是如何工作的.         ...

  8. MIT 6.828 JOS学习笔记12 Exercise 1.9

    Lab 1中Exercise 9的解答报告 Exercise 1.9: 判断一下操作系统内核是从哪条指令开始初始化它的堆栈空间的,以及这个堆栈坐落在内存的哪个地方?内核是如何给它的堆栈保留一块内存空间 ...

  9. MIT 6.828 JOS学习笔记13 Exercise 1.10

    Lab 1 Exercise 10 为了能够更好的了解在x86上的C程序调用过程的细节,我们首先找到在obj/kern/kern.asm中test_backtrace子程序的地址, 设置断点,并且探讨 ...

随机推荐

  1. java 配置在.properties文件中的常量

    不让用常量类,那就用.properties文件配置,放在根目录. import java.util.HashMap; import java.util.Iterator; import java.ut ...

  2. 深入理解JavaScript系列(45):代码复用模式(避免篇)

    介绍 任何编程都提出代码复用,否则话每次开发一个新程序或者写一个新功能都要全新编写的话,那就歇菜了,但是代码复用也是有好要坏,接下来的两篇文章我们将针对代码复用来进行讨论,第一篇文避免篇,指的是要尽量 ...

  3. show_space

    create or replace procedure show_space( p_segname_1 in varchar2,p_space in varchar2 default 'AUTO',p ...

  4. jquery获取子元素

    Jquery获取子元素的方法有2种,分别是children()方法和find()方法. 下面我们分别来使用这两种方法,看看它们有何差异. children()方法:获取该元素下的直接子集元素 find ...

  5. 预防XSS方法:HtmlEncode和JavaScriptEncode(转)

    XSS又称CSS,全称Cross SiteScript,跨站脚本攻击,是Web程序中常见的漏洞,XSS属于被动式且用于客户端的攻击方式,所以容易被忽略其危害性.其原理是攻击者向有XSS漏洞的网站中输入 ...

  6. 一:SpringDataJPA

    一:spring data jpa介绍 spring data:其实spring data就是spring提供了一个操作数据的框架.而spirng data jpa只是spring data框架下的一 ...

  7. 从服务器下载文件 DownloadServlet()

    .html代码 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <t ...

  8. linux系统下部署项目

    一.修改防火墙设置,开放对应的端口 修改Linux系统防火墙配置需要修改 /etc/sysconfig/iptables 这个文件,如果要开放哪个端口,在里面添加一条  -A RH-Firewall- ...

  9. 如何正确实现 IDisposable 接口

    MSDN建议按照下面的模式实现IDisposable接口: public class Foo: IDisposable { public void Dispose() { Dispose(true); ...

  10. 【每日一linux命令】

    参考文章 1.[每日一linux命令]