【noip模拟】tree
Time Limit: 1000 ms Memory Limit: 128 MB

[吐槽]
点分治点分治点分治
嗯。。场上思考树状数组的时候好像傻掉了。。反正就是挂了就是了。。
[题解]
首先如果没有环的话就是一道十分简单的点分治啦
但是这题有环啊
考虑强行变树
从题目各种谜一般的描述中得出来的结论是:$m<=n$
其实也就是说最多只有一个环
那么就有一个很直接的想法,先把唯一的一个环找出来,断掉其中的一条边
这样就使它变成一棵树了,直接跑一遍点分就好
考虑断掉的那条边
这样统计有一个很明显的问题:经过断开那条边的情况全部都没有算进去
所以现在就考虑怎么算过这条边的ans
首先我们可以将这个环摊开变成这样:

然后发现这个东西其实就是一条“链”上面有若干棵树
断开的那条边显然就是连接这条“链”一头一尾的边(为了方便描述,将这条断开的边记作$(x,y)$)
我们定义
$rt_i$表示$i$所属的子树的根节点
$dis_i$ 表示$i$到$rt_i$的的路径上的点数
$left_i$表示$rt_i$到这条“链”头(也就是图中编号为1的点)的节点数
$right_i$表述$rt_i$到这条“链”尾(图中编号为5的点)的节点数
那么要算一条过$(x,y)$的路径$(i,j)$的点数的话,显然就是子树里面的距离+链上要走的距离
也就是 $dis_i+dis_j+left_i+right_j$ ($rt_i$在$rt_j$左边)

那么就可以用一个树状数组来搞定了
考虑怎么统计
(其实实现起来并不用上面的那些奇妙数组)
我们可以先将链上的点(也就是各个子树的根节点)编个号
那么对于一个这条链上面的第$i$和第$j$ $(i<j)$ 个点,那么链上要走的距离就为 $i+(len-j+1)$
其中$len$表示的是链的长度
然后将式子上一步中求路径上点数的式子稍微整理一下,得到
$(dis_i+i)+(dis_j+len-j+1) (i<j) $
所以我们可以从左往右一个一个点处理
先将当前点$i$子树内的$dis$处理出来
然后对于每一个$dis_j (j \in subtree(i))$ ,在树状数组里面查询大于等于$k-dis_j-(len-j+1)$的数量(原因在后面解释)
查询完了之后将$dis_j+j$丢入树状数组中
这么处理的原因显然
整理过后的式子可以分为两部分,分别只与$i$和$j$有关
然后因为我们是从左到右处理链上面的点的,所以可以保证查询到的点是在当前点的前面的
然后这题就十分愉快地解决啦
[一些小细节]
因为这题是求>=的方案数
所以树状数组要十分愉快地反过来(也就是insert的时候是x-=x&-x,query的时候是x+=x&-x,见代码)
以及因为insert的时候是dis+i,所以上限应该是2*n
以及要用long long
嗯大概就是这样ovo
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int MAXN=;
int h[MAXN],size[MAXN],mx[MAXN];
ll dis[MAXN];
bool vis[MAXN];
int n,m,k,tot,rt,rt_mx;
ll ans,num;
struct xxx
{
int y,next;
bool flag;
}a[MAXN*];
struct data
{
ll c[MAXN*];
int insert(int x,ll delta) {_insert(x,delta);}
int _insert(int x,ll delta)
{
for (;x;x-=x&-x) c[x]+=delta;
}
ll query(int x) {return _query(x);}
ll _query(int x)
{
ll ret=;
if (x<) x=;
for (;x<=*n;x+=x&-x) ret+=c[x];
return ret;
}
}c;
int pre[MAXN],cir[MAXN];
int add(int x,int y);
int dfs(int x);
int dfs_size(int x,int fa);
int dfs_root(int r,int x,int fa);
int get_dis(int x,int fa,int d);
int get_cir(int fa,int x);
ll cal(int x,int d);
bool cmp(int x,int y){return x>y;}
int solve_cir(); int main()
{
freopen("a.in","r",stdin);
freopen("a.out","w",stdout); int x,y,z;
scanf("%d%d%d",&n,&m,&k);
tot=;
memset(h,-,sizeof(h));
for (int i=;i<=m;++i)
{
scanf("%d%d",&x,&y);
add(x,y); add(y,x);
}
if (m+==n) {dfs(); printf("%lld\n",ans); return ;}
cir[]=;
get_cir(,);
solve_cir();
} int add(int x,int y)
{
a[++tot].y=y; a[tot].next=h[x]; h[x]=tot; a[tot].flag=true;
} int dfs(int x)
{
rt=,rt_mx=n;
dfs_size(x,);
dfs_root(x,x,);
ans=ans+cal(rt,);
vis[rt]=true;
for (int i=h[rt];i!=-;i=a[i].next)
if (!vis[a[i].y]&&a[i].flag)
{
ans=ans-cal(a[i].y,);
dfs(a[i].y);
}
} int dfs_size(int x,int fa)
{
size[x]=;
mx[x]=;
for (int i=h[x];i!=-;i=a[i].next)
if (a[i].y!=fa&&!vis[a[i].y]&&a[i].flag)
{
dfs_size(a[i].y,x);
size[x]+=size[a[i].y];
mx[x]=max(mx[x],size[a[i].y]);
}
} int dfs_root(int r,int x,int fa)
{
mx[x]=max(mx[x],size[r]-size[x]);
if (rt_mx>mx[x]) rt_mx=mx[x],rt=x;
for (int i=h[x];i!=-;i=a[i].next)
if (a[i].y!=fa&&!vis[a[i].y]&&a[i].flag)
dfs_root(r,a[i].y,x);
} int get_dis(int x,int fa,int d)
{
dis[++num]=d;
for (int i=h[x];i!=-;i=a[i].next)
if (a[i].y!=fa&&!vis[a[i].y]&&a[i].flag)
get_dis(a[i].y,x,d+);
} ll cal(int x,int d)
{
num=;
get_dis(x,,d);
int left=,right=num;
ll re=;
sort(dis+,dis++num,cmp);
while (left<right)
{
while (dis[left]+dis[right]+<k&&left<right) --right;
re+=right-left;
++left;
}
return re;
} int get_cir(int fa,int x)
{
int u;
vis[x]=true; pre[x]=fa;
for (int i=h[x];i!=-;i=a[i].next)
{
u=a[i].y;
if (u==fa) continue;
if (vis[u])
{
a[i].flag=false; a[i^].flag=false;
for (int j=x;j!=u;j=pre[j]) cir[++cir[]]=j;
cir[++cir[]]=u;
return ;
}
get_cir(x,u);
if (cir[]) return ;
}
} int solve_cir()
{
for (int i=;i<=n;++i) vis[i]=false;
dfs();
for (int i=;i<=n;++i) vis[i]=false;
for (int i=;i<=cir[];++i) vis[cir[i]]=true;
for (int i=;i<=cir[];++i)
{
num=;
get_dis(cir[i],,);
for (int j=;j<=num;++j)
ans+=c.query(k-dis[j]-(cir[]-i+));
for (int j=;j<=num;++j)
c.insert(dis[j]+i,);
}
printf("%lld\n",ans);
}
挫挫的代码
【noip模拟】tree的更多相关文章
- 8.22 NOIP 模拟题
8.22 NOIP 模拟题 编译命令 g++ -o * *.cpp gcc -o * *.c fpc *.pas 编译器版本 g++/gcc fpc 评测环境 位 Linux, .3GHZ CPU ...
- NOIP 模拟赛
NOIP 模拟赛 思路:求 n , m 的 gcd,然后用 n , m 分别除以 gcd:若 n 或 m 为偶数,则输出 1/2. 特别的,当 n = m = 1 时,应输出 1/1 #include ...
- 8.1 NOIP模拟11
8.1 NOIP模拟 11 今天上午返校之后,颓了一会,然后下午就开始考试,中午睡着了,然后刚开始考试的时候就困的一匹,我一看T1,woc,这不是之前线段树专题的题啊,和那道题差不多,所以我..... ...
- 2019.7.29 NOIP模拟测试10 反思总结【T2补全】
这次意外考得不错…但是并没有太多厉害的地方,因为我只是打满了暴力[还没去推T3] 第一题折腾了一个小时,看了看时间先去写第二题了.第二题尝试了半天还是只写了三十分的暴力,然后看到第三题是期望,本能排斥 ...
- NOIP模拟 17.8.15
NOIP模拟17.8.15 A 债务文件名 输入文件 输出文件 时间限制 空间限制debt.pas/c/cpp debt.in debt.out 1s 128MB[题目描述]小 G 有一群好朋友,他们 ...
- noip模拟23[联·赛·题]
\(noip模拟23\;solutions\) 怎么说呢??这个考试考得是非常的惨烈,一共拿了70分,为啥呢 因为我第一题和第三题爆零了,然后第二题拿到了70分,还是贪心的分数 第一题和第二题我调了好 ...
- noip模拟27[妹子图·腿·腰](fengwu半仙的妹子们)
\(noip模拟27\;solutions\) 这次吧,我本来以为我能切掉两个题,结果呢??只切掉了一个 不过,隔壁Varuxn也以为能切两个,可惜了,他一个都没切...... 确实他分比我高一点,但 ...
- noip模拟6(T2更新
由于蒟弱目前还没调出T1和T2,所以先写T3和T4.(T1T2更完辣! update in 6.12 07:19 T3 大佬 题目描述: 他发现katarina大佬真是太强了,于是就学习了一下kata ...
- NOIP模拟赛20161022
NOIP模拟赛2016-10-22 题目名 东风谷早苗 西行寺幽幽子 琪露诺 上白泽慧音 源文件 robot.cpp/c/pas spring.cpp/c/pas iceroad.cpp/c/pas ...
- contesthunter暑假NOIP模拟赛第一场题解
contesthunter暑假NOIP模拟赛#1题解: 第一题:杯具大派送 水题.枚举A,B的公约数即可. #include <algorithm> #include <cmath& ...
随机推荐
- [Uva10294]Arif in Dhaka
[Uva10294]Arif in Dhaka 标签: 置换 Burnside引理 题目链接 题意 有很多个珠子穿成环形首饰,手镯可以翻转和旋转,项链只能旋转.(翻转过的手镯相同,而项链不同) 有n个 ...
- 5、flask之信号和mateclass元类
本篇导航: flask实例化参数 信号 metaclass元类解析 一.flask实例化参数 instance_path和instance_relative_config是配合来用的:这两个参数是用来 ...
- easyui验证扩展
问题描述: 如上所示:当用户添加信息时,必须保证一个队伍一天只能有一条数据.所以在选择了报表日期的时候必须查询数据库里面当前队伍这一天的数据是否存在.如果不存在,即当前日期队伍没有数据,就可以进行数据 ...
- YUM安装软件
YUM:介绍.工作流程.本地yum.网络yum.yum的相关命令 一.What is YUM YUM是基于rpm但更胜于rpm的软件管理工具 YUM的优点: 1.更方便的管理rpm软件包 2.自动解决 ...
- 【netty这点事儿】ByteBuf 的使用模式
堆缓冲区 最常用的 ByteBuf 模式是将数据存储在 JVM 的堆空间中. 这种模式被称为支撑数组(backing array), 它能在没有使用池化的情况下提供快速的分配和释放. 直接缓冲区 直接 ...
- Web API 之承载宿主IIS,SelfHost,OwinSelfHost
Asp.Net WebAPI这个大家应该都不陌生,在我的理解范围中就是数据提供和交换的一个方式,相比与WCF,WS而言,更加的简单轻量,但是在部署web Api的时候,一般往往需要与a ...
- C#语言Devdevexpress控件chart在C/S框架中的使用
声明.数据库连接机制框架已经写好.框架模式是MVC模式.就以我的from测试.我的做法是在查询页面创建一个按钮,然后在这个按钮上绑定一个点击事件.点击查询按钮把查询条件传到需要显示图例的页面.查询页面 ...
- Java文件复制与读写
函数介绍 public String readLine():每次读取文件的一行,当文件读取完毕时,返回null public int read(byte[] b):将文件内容读取到字节数组b ...
- 高并发场景下的httpClient优化使用
1.背景 我们有个业务,会调用其他部门提供的一个基于http的服务,日调用量在千万级别.使用了httpclient来完成业务.之前因为qps上不去,就看了一下业务代码,并做了一些优化,记录在这里. 先 ...
- 用Node.JS+MongoDB搭建个人博客(页面模板)(五)(结束)
<差不多先生> 我是差不多先生,我的差不多是天生.也代表我很天真,也代表我是个闲人.这差不多的人生,总是见缝插针. 求学的道路上总是孤独的,即使别人不理解我,认为我是奇葩!但没关系,我会坚 ...
