首页 > 其他分享 >CF1943C Tree Compass

CF1943C Tree Compass

时间:2024-08-13 23:06:27浏览次数:7  
标签:putchar ll Tree write 1ll Compass frac CF1943C define

思路:

考虑往直径方向想,设直径的长度为 \(d\)。

首先可以注意到一个性质:

  • 每次操作最多只会覆盖住直径的 \(2\) 个点,那么答案的下界即为 \(\lceil \frac{d}{2} \rceil\)。

分类讨论一下。

若 \(d\) 为奇数,则存在唯一的一个直径中心 \(u\):

  • 那么答案为 \((u,0),(u,1),\cdots,(u,\lceil \frac{d-1}{2} \rceil)\)。

  • 最优次数是 \(\lceil \frac{d}{2} \rceil\) 次。

若 \(d\) 为偶数,则存在两个直径中心 \(u,v\):

  • 若 \(d \bmod 4 = 0\) 时:

    • 那么答案为 \((u,1),(v,1),(u,3),(v,3),\cdots,(u,\frac{d}{2}-1),(v,\frac{d}{2}-1)\)。

    • 最优次数是 \(\frac{d}{2}\)。

    • 这样是两者是完全错开的。

  • 若 \(d \bmod 4 = 2\) 时:

    • 那么答案为 \((u,0),(u,1),\cdots,(u,\frac{2}{d})\)。

    • 最优次数是 \(\frac{d}{2}+1\)。

这里证明一下为什么当 \(d \bmod 4 = 0\) 时不能取到答案的下界。

注意到若 \(x,y\) 能被同时取到当且仅当 \(\operatorname{dis}(x,y)\) 为偶数。

设 \(L\) 为直径的一个端点,那么 \(\operatorname{dis}(L,x)+\operatorname{dis}(L,y)\) 的奇偶性等价于 \(2*(奇数/偶数)+偶数=偶数\)。

因为 \(d \bmod 4 = 2\),所以 \(\sum \operatorname{dis}(L,i) = \frac{d \times (d-1)}{2} \bmod 4 = 1\),则这个和式一定不是偶数,故无法达到下界。

时间复杂度为 \(O(TN)\)。

完整代码:

#include<bits/stdc++.h>
#define Add(x,y) (x+y>=mod)?(x+y-mod):(x+y)
#define lowbit(x) x&(-x)
#define pi pair<ll,ll>
#define pii pair<ll,pair<ll,ll>>
#define iip pair<pair<ll,ll>,ll>
#define ppii pair<pair<ll,ll>,pair<ll,ll>>
#define fi first
#define se second
#define full(l,r,x) for(auto it=l;it!=r;it++) (*it)=x
#define Full(a) memset(a,0,sizeof(a))
#define open(s1,s2) freopen(s1,"r",stdin),freopen(s2,"w",stdout);
using namespace std;
typedef double db;
typedef unsigned long long ull;
typedef long long ll;
bool Begin;
const ll N=2e3+10;
inline ll read(){
    ll x=0,f=1;
    char c=getchar();
    while(c<'0'||c>'9'){
        if(c=='-')
          f=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9'){
        x=(x<<1)+(x<<3)+(c^48);
        c=getchar();
    }
    return x*f;
}
inline void write(ll x){
	if(x<0){
		putchar('-');
		x=-x;
	}
	if(x>9)
	  write(x/10);
	putchar(x%10+'0');
}
ll T,n,x,y,id,sum,cnt;
ll a[N],d[N],fa[N];
vector<ll> E[N];
void add(ll u,ll v){
    E[u].push_back(v);
    E[v].push_back(u);
}
void dfs(ll u,ll f){
    for(auto v:E[u]){
        if(v==f)
          continue;
        fa[v]=u;
        d[v]=d[u]+1;
        dfs(v,u);
    }
}
void solve(){
    cnt=0;
    n=read();
    for(int u,v,i=1;i<n;i++){
        u=read(),v=read();
        add(u,v);
    }
    fa[1]=d[1]=sum=0;
    dfs(1,1);
    for(int i=1;i<=n;i++){
        if(d[i]>=sum){
            sum=d[i];
            id=i;
        }
    }
    //cerr<<id<<'\n';
    fa[id]=d[id]=sum=0;
    dfs(id,id);
    for(int i=1;i<=n;i++){
        if(d[i]>=sum){
            sum=d[i];
            id=i;
        }
      //  cerr<<d[i]<<' ';
    }
   // cerr<<'\n';
    while(id){
        a[++cnt]=id;
        id=fa[id];
    }
    if(cnt&1ll){
        x=a[(cnt+1)>>1ll];
        write((cnt+1)>>1ll);
        putchar('\n');
        for(int i=0;i<((cnt+1)>>1ll);i++){
            write(x);
            putchar(' ');
            write(i);
            putchar('\n');
        }
    }
    else{
        x=a[cnt>>1ll],y=a[(cnt>>1ll)+1];
        if(cnt&3ll){
            write((cnt>>1ll)+1);
            putchar('\n');
            for(int i=0;i<=(cnt>>1ll);i++){
                write(x);
                putchar(' ');
                write(i);
                putchar('\n');
            }
        }
        else{
            write(cnt>>1ll);
            putchar('\n');
            for(int i=1;i<(cnt>>1ll);i+=2){
                write(x);
                putchar(' ');
                write(i);
                putchar('\n');
                write(y);
                putchar(' ');
                write(i);
                putchar('\n');
            }
        }
    }
    for(int i=1;i<=n;i++)
      E[i].clear();
}
bool End;
int main(){
    T=read();
    while(T--)
      solve();
	cerr<<'\n'<<abs(&Begin-&End)/1048576<<"MB";
	return 0;
}

标签:putchar,ll,Tree,write,1ll,Compass,frac,CF1943C,define
From: https://www.cnblogs.com/rgw2010/p/18357900

相关文章

  • CF1149C Tree Generator™
    题意\(n\)个点,\(m\)个询问。给你一棵树的括号序列,输出它的直径。有\(m\)次询问,每次询问表示交换两个括号,输出交换两个括号后的直径(保证每次操作后都为一棵树)输出共\(m+1\)行。\(3\len\le100\,000,1\leq\le100\,000\)——洛谷翻译。思路我们不难想到,一个......
  • clickhouse_mergeTree
    MergeTree类型Clickhouse中最强大的表引擎当属MergeTree(合并树)引擎及该系列(*MergeTree)中的其他引擎。MergeTree系列的引擎被设计用于插入极大量的数据到一张表当中。数据可以以数据片段的形式一个接着一个的快速写入,数据片段在后台按照一定的规则进行合并。相比在插入时不......
  • QSortFilterProxyModel和QTreeView排序功能
    1、需求,创建一个树有多层结构,同一层按照插入顺序逆序排列; ui.treeView->setHeaderHidden(true);//treewidget头标题是否显示,此处隐藏标题//ui.treeWidget->header()->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);ui.treeView->header()->s......
  • el-tree 组件自定义样式 最后一级flex,其余级别正常block
    先上需求的效果图el-tree的样式一般全都是block换行的,如下图先分析一下,1.树结构的级别是不确定的,但是样式上要求最后一个层级需要横着排列,其余竖着排,超出需要换行2.如何找到每一个数据项的最后一级呢?3.找到之后怎么办?ok,then,1.先通过插槽吧,因为这样咱们可以自定义最后一......
  • BINARY-SEARCH-TREES(二叉搜索树)
        一颗二叉搜索树是以一颗二叉树来组织的。除了数据之外,每个结点还包含属性left,right和p,它们分别指向结点的左孩子,右孩子和双亲。如果某个孩子结点和父结点不存在,则相应属性值为NULL。根结点是树中唯一父指针为NULL的结点。    二叉搜索树对任何结点x,其左子......
  • F - Perfect Matching on a Tree
    原题链接分析考虑两个点对\((a,b),(x,y)\)如果点对\((a,b)\)的路径与点对\((x,y)\)的路径不存在共同的点,那么此时我们交换\(a,x\),则有点对\((x,b),(a,y)\)此时两个点对的路径相交,且\(dis(x,b)+dis(a,y)\gtdis(a,b)+dis(x,y)\)所以,最后的答案一定是一条路径与其他所......
  • Qt自定义TreeWidget,实现展开折叠按钮在右侧,且一条竖直线上对齐
    效果如下:图片随便找的,可能需要调下样式,代码复制可用,留给有需要的人。 #ifndefCustomTreeWidget_h__#defineCustomTreeWidget_h__#include<QTreeWidget>#include<QPushButton>classCCustomTreeWidget:publicQTreeWidget{ Q_OBJECTpublic: CCustomTreeW......
  • [AGC052B] Tree Edges XOR
    好题,可以直接作为套路记录一下。[AGC052B]TreeEdgesXOR题目大意:给你一棵树,有奇数个点,每个边有边权\(w_i\)。每次你可以选出一条边,将和这条边的所有相邻的边都异或这条边的边权,问你能否得到最终状态(操作次数不定)。思路:首先,上来会发现每次操作影响的边十分多,肯定无法直接维......
  • Dsu On Tree
    前置知识:树链剖分的一些东西会打暴力DSUOnTree是啥中文名:树上启发式合并/静态链分治先考虑启发式合并是啥:说到启发式合并,那么常见的就是并查集了。我们将小的集合合并到大的集合中,就可以变成\(O(n\logn)\)神奇让高度小的树成为高度较大的树的子树,这个优化可......
  • Windows图形界面(GUI)-MFC-C/C++ - 树形视图(Tree Control) - CTreeCtrl
    公开视频-> 链接点击跳转公开课程博客首页-> ​​​链接点击跳转博客主页目录树形视图(TreeControl)-CTreeCtrl创建和初始化添加和删除项获取和设置项属性操作项项选择变化项双击项展开示例代码树形视图(TreeControl)-CTreeCtrl创建和初始化Subclas......