Party Company

大意:

有一颗树,n个节点,每一个节点有一个对应的权值,并且满足儿子的权值<父亲的权值。现有m个区间【L,R】,每一个区间会给定一个初始点(举办方),其它点想要加入该区间,需同时满足以下条件:

1.其权值在该区间内(左右包含)

2.其父亲/儿子已经加入了该区间

现在给定树和若干区间,求每一个节点能被多少个区间覆盖。

n,m<=1e5

思路:

感觉还算是比较综合的一道题了。

稍微转化以下题意,不难发现,对于每一个区间以及其初始点,我们其实就是要找一个包含该初始点的连通块,其中连通块内的每一个点的权值都在该区间内,然后里面的每一个点的答案就可以+1了。

不难证明该思路的合理性。设该思路每次对应的点数是A,实际答案是B

先证明A<=B:

首先连通块内的点的权值都是满足条件的,并且它们与初始点的路径上的每一个点都被加入了集合,所以A<=B的。

证明A>=B:

不在连通块内的点,就算它的权值在区间内部,但是其与初始点的路径上必然存在某一个点没有被加入集合,所以该点一定不在答案集合中,故A<=B

这就得到了该思路的合理性。

那么考虑到每一个点的父亲只有一个,赛时也很快就想到了先去找到深度最浅的满足条件的点。为什么这么做?因为就算是连通块,也依然是有些混乱,肯定不如我们最会处理的子树问题和区间问题来的清晰,所以就要考虑将其转化。

所以首先用树上倍增找到初始点到根的路径上的满足权值要求的深度最浅的点RT,那么不难发现能被加入该集合的所有点一定都在RT的子树内,否则,其与RT的lca就会是一个深度更浅的点,但RT已经是能找到的深度最浅的点了,所以矛盾。

void init_dfs(ll id,ll p)
{fa[id][0]=p;for(int i=1;i<=20;++i) fa[id][i]=fa[fa[id][i-1]][i-1];for(int i=head[id];i!=-1;i=edge[i].next){ll y=edge[i].t;if(y==p) continue;init_dfs(y,id);}
}
ll jump(ll id,ll tar)
{ll now=id;for(int i=20;i>=0;--i){if(age[fa[now][i]]<=tar&&fa[now][i]!=0) now=fa[now][i];} return now;
}

到这里还是很好处理的,并且我们也已经成功把问题转化到RT的子树上了。并且,由于子树内的点的权值都小于RT的权值,相当于它们都满足权值<=R的条件,所以只要权值>=L就一定满足条件。你可能会想到,就算权值>=L,但有可能其某个父亲没有加入集合,这样就是不合理的,但是我们同样考虑到权值的单调性,祖先权值一定>儿子权值,所以这种情况不存在。因此,对于子树中的点,我们现在只用考虑其权值>=L即可。但是赛时就是卡在了这里,不知道该怎么做下去了。(还是太年轻~)

看到别人代码时还是有点傻眼了,没想到这么简单(其实也不简单,但人家真的写的很简单,哭...)。我们考虑离线,这个不难想,在线处理那么多询问肯定不太行。对于每一次的区间,我们先找到它对应的RT,然后把这个区间的信息存在RT里。最后做一次dfs,对权值开一个树状数组(1e5),对于每一个节点,将存放在该点的区间信息的L值在树状数组中+1,那么改点的答案就是一个树状数组的前缀和了,这个显然。然后该点一定是对应区间的RT,所以向下dfs时,其子树的节点也能利用这些区间。但是别的子树的节点不行,所以子树dfs完之后,要把加过的L值-1,去除影响,这个也就是一句话的事,然后就好了。

#include<bits/stdc++.h>
using namespace std;
#define ll int
#define endl '\n'
#define low(x) x&(-x)
const ll N=1e5+10;
struct ty
{ll t,l,next;
}edge[N<<1];
ll cn=0;
ll head[N];
ll n,m;
ll age[N];
ll fa[N][25];
ll a,b,c;
struct que
{ll l,r;
};
vector<que> vt[N];
ll ans[N];
void init_dfs(ll id,ll p)
{fa[id][0]=p;for(int i=1;i<=20;++i) fa[id][i]=fa[fa[id][i-1]][i-1];for(int i=head[id];i!=-1;i=edge[i].next){ll y=edge[i].t;if(y==p) continue;init_dfs(y,id);}
}
ll jump(ll id,ll tar)
{ll now=id;for(int i=20;i>=0;--i){if(age[fa[now][i]]<=tar&&fa[now][i]!=0) now=fa[now][i];} return now;
}
void add_edge(ll a,ll b,ll c)
{edge[++cn].t=b;edge[cn].l=c;edge[cn].next=head[a];head[a]=cn;
}
ll tr[N<<1];
void add(ll x,ll y)
{while(x<=N){tr[x]+=y;x+=low(x);}
}
ll sum(ll x)
{ll ans=0;while(x){ans+=tr[x];x-=low(x);}return ans;
}
void dfs(ll id,ll p)
{for(auto i:vt[id]){add(i.l,1);}ans[id]=sum(age[id]);for(int i=head[id];i!=-1;i=edge[i].next){ll y=edge[i].t;if(y==p) continue;dfs(y,id);}for(auto i:vt[id]){add(i.l,-1);}
}
void solve()
{cin>>n>>m;for(int i=1;i<=n;++i){cin>>a>>b;age[i]=a;if(b!=i){add_edge(i,b,1);add_edge(b,i,1);}}
//  for(int i=1;i<=n;++i) cout<<age[i]<<' ';
//  cout<<endl;init_dfs(1,0);for(int i=1;i<=m;++i){cin>>a>>b>>c;ll dsp=jump(a,c);//cout<<"alex "<<dsp<<endl;que s;s.l=b;s.r=c;vt[dsp].push_back(s);}dfs(1,0);for(int i=1;i<=n;++i) cout<<ans[i]<<" ";
}
int main()
{ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);memset(head,-1,sizeof head);solve();return 0;
}

Between Us

大意:

给定一张无向图,现在要将这张图分成两个部分,两张子图连接处的边会去除,要求满足分好之后每一个节点的度数都是奇数。问是否存在这样的分法

1 ≤ n ≤ 100 , 1 ≤ m ≤ n × ( n − 1 ) / 2

思路:

思路有点小清新,而且实现也是非常的简单,是看了会让人心情舒畅的题。

虽然但是,我们队赛时完全没看过这道题(看了也不会)。

令a【i】表示i点被分配到了哪一个集合。1表示1集合,0表示0集合(废话)

那么就有如下式子:

i点度数是奇数,a【i】=1:,也就是分出偶数个点去0集合

i点度数是奇数,a【i】=0:,也就是分出偶数个点去1集合

i点度数是偶数,a【i】=1:,也就是分出奇数个点去0集合

i点度数是偶数,a【i】=0:,也就是分出奇数个点去1集合

那么就不难发现,若i点度数是奇数,,若i点度数为偶数,.

然后建立对应的方程组,高斯消元就好了。就没了。。。

#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define ll int
const ll N=210;
ll n,m;
vector<ll> vt[N];
ll du[N];
bitset<N> S[N];
ll a,b;
ll all,len;
int guass()
{int now=0,last=0;int cnt=0;for(int i=1;i<=n&&now<=len;++i){int j=now;while(j<=len&&!S[j][i]) j++;if(j>len) continue;else cnt++;if(j!=now) swap(S[j],S[now]);for(int k=1;k<=len;++k){if(k==now) continue;if(S[k][i]==0) continue;S[k]^=S[now];}now++; }
//  for(int i=0;i<len;++i)
//  {
//      cout<<S[i]<<endl;
//  }for(int i=now;i<=len;++i){if(S[i][all]==1) return 0;}return 1;
}
void solve()
{cin>>n>>m;all=n+1;len=n;for(int i=1;i<=m;++i){cin>>a>>b;vt[a].push_back(b);vt[b].push_back(a);du[a]++;du[b]++;}for(int i=1;i<=n;++i){if(du[i]&1) //奇数{S[i][i]=1;for(ll j:vt[i]){S[i][j]=1;}S[i][all]=0;} else{for(ll j:vt[i]){S[i][j]=1;}S[i][all]=1;}}if(guass()) cout<<"Y";else cout<<"N";
}
int main()
{solve();return 0;
} 

2021年巴西icpc重现赛补题相关推荐

  1. 2108889队2021年数学建模美赛C题花絮视频!

    2108889队2021年数学建模美赛C题花絮视频

  2. ​2021年数模国赛A题国二摘要及经验分享(回忆篇,附部分代码)

    以2021年数模国赛A题为例,主要分享内容有:如何写好国赛摘要.部分解题思路和排版技巧.接下来,干货走起. 题目重述:" FAST "主动反射面的形状调节 中国天眼( FAST ) ...

  3. 林大5.1训练赛补题

    林大5.1训练赛补题 A.凸多边形曼哈顿 E.矩阵快速幂 I.线段dp A.凸多边形曼哈顿 题意:给你一个凸多边形,问你当其中K边形的最大dis[]是多少? 思路:首先是要发现K>=4的时候答案 ...

  4. 2021年数学建模国赛C题问题三详细思路和代码

    2021年数学建模国赛C题问题三详细思路和代码 1 问题分析 问题三要求压缩成本.减少转运及仓储的成本.降低转运损耗率,并制定对应的订购方案和转运方案,最大的特点在于没有供应商数量限制,故每周的供应商 ...

  5. 2021年数学建模国赛C题问题二详细思路和代码

    2021年数学建模国赛C题问题一详细思路和代码 说明: 本思路仅为小编个人思路,其中关于本文中给出的AdaBoost回归预测模型于今年的 国赛参考评分标准有所出入,所以本题思路为个人创新思路,不一定符 ...

  6. 2021山东省省赛补题

    cf传送门 前言 在gym看到,知道山东省很nb所以写了. 补题含大量借鉴大佬代码() F Birthday Cake 题意:给定n个串,求有多少对串能拼出平方串(能够表示成两个相同的字符串连接在一起 ...

  7. 2019ICPC上海区域赛 补题(12/13) 总结

    前言: 个人的 ICPCICPCICPC 第一站,还是值得记录一下的(虽然咕到现在才记录),总体而言体验很不错,比赛兼旅游.这套题总体印象就是树树树图,作为队里数据结构兼图论选手,这次也确实写了大部分 ...

  8. 开源一份2021年数学建模国赛B题全国二等奖的完整论文 代码 以及答辩PPT

    写在前面 本人曾参加2020年数学建模国赛(优胜奖)以及2021年数学建模国赛(全国二等奖),并两次担任了队长,主要负责建模和代码,也承担部分写作任务.在建模之前也看了网上的很多优秀论文,但这些论文是 ...

  9. icpc 2020沈阳区域赛补题

    2020沈阳区域赛 H 这题是一道典型dp 但是需要用滚动数组优化空间, 在状态转移的时候需要考虑一下是否满足天数条件. 我真的吐了,debug改了半天之后发现错误原因是: 排序应该是 sort(v+ ...

最新文章

  1. go chapter 8 - 初始化对象
  2. linux nslcd服务,Ubuntu 通过ldap集成AD账号登录(nslcd方式)
  3. 清华大学《操作系统》(十八):管程于信号量
  4. java后台获取流_java后台发送请求获取数据,并解析json数据
  5. GSL数学库解多参数方程
  6. windows PAE扩展和AWE编程
  7. 大数据查询平台有哪些?Hadoop数据查询组件分析
  8. 【供应链架构day12】电商仓储WMS的业务UseCase
  9. Plant Ecology Journal Club, 2018
  10. Springcloud+Seata+nacos 分布式事务项目搭建 AT模式
  11. 字符串相乘——大整数乘法
  12. php中相关乱码处理
  13. Filecoin周报-39期:Filecoin Testnet/3按约定如期上线!
  14. 前端、vue、Vue3弹幕实现;前端CSS实现弹幕
  15. 已知二叉树:先序和中序求后序/后序和中序求先序
  16. 城市路口闯红灯监测系统
  17. oracle人民币转大写,Oracle 小写金额转换为大写
  18. 虚拟机搭建单机版Hadoop教程(惨痛经历)
  19. word-取消超链接的两个步骤
  20. 推荐一个免费阅读神器

热门文章

  1. shm php,php实现共享内存进程通信函数之_shm
  2. linux网络编程 copymemory,在VB6中用CopyMemory拷贝字符串的种种猫腻(一)
  3. 关于U盘启动操作系统《30天自制操作系统》
  4. 操作系统之哲学原理连载之二
  5. 有趣的 linux命令行
  6. Spark 系列(一)—— Spark简介
  7. python 读取outlook_通过Python读取Outlook事件
  8. python中load_iris_在python中利用KNN实现对iris进行分类的方法
  9. 2021安徽护理副高考试成绩查询,全国卫生人才网2021护士资格考试合格成绩查询官网...
  10. inline内联函数(声明前加inline还是定义前加inline)