题目链接:2018-2019 ACM-ICPC, Asia Xuzhou Regional Contest

A. Rikka with Minimum Spanning Trees

题意:

给出一个随机算法生成边的信息,然后求最小生成树的个数以及其权值的乘积。

题解:

这个随机算法有点神奇...基本不会有重复的边出现,所以其实只用求MST就行了。当然,其实通过样例也可以猜出来,样例生成了1W条边,但最后的answer就为最小生成树权值,所以可以直接根据这个来猜一发,注意一下判断是否连通就行了。

代码如下:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 1e5+;
const int MAXM = 3e5+;
const int MOD = 1e9+;
const double eps = 1e-;
typedef unsigned long long ull;
#define rep(i,a,b) for(int i = (a);i<=(b);i++)
struct Edge{
int u,v;
ull w;
bool operator <(const Edge &ds)const{
return w<ds.w;
}
}e[MAXM];
int n,m,fa[MAXN];
int t,tot;
//double G[MAXN][MAXN];
ull k1,k2;
ull ans=;
ull xorShift128Plus(){
ull k3=k1,k4=k2;
k1=k4;
k3 ^= k3<<;
k2 = k3 ^ k4 ^ (k3 >>) ^(k4 >>);
return k2 +k4;
}
void gen(){
cin >>n >>m >>k1 >>k2;
int u,v;
ull w;
tot = ans = ;
rep(i,,m){
u = xorShift128Plus()%n+;
v = xorShift128Plus()%n+;
w = xorShift128Plus();
if(u == v) continue ;
//cout <<u<<' ' <<v<<' ' <<w <<'\n';
e[++tot] = {u,v,w};
}
}
int find(int x){
return x==fa[x]?x:fa[x] = find(fa[x]);
}
bool kruskal(){
int ss=;
sort(e+,e++tot);
rep(i,,n)fa[i] =i;
rep(i,,tot){
int a = find(e[i].u),b =find(e[i].v);
if(a!=b){
fa[a] =b;
ans = (ans +e[i].w%MOD)%MOD;
ss++;
}
}
return ss==n-;
}
int main() {
ios::sync_with_stdio(false);cin.tie() ;
cin >>t;
while(t--){
gen();
if(!kruskal()){
cout << <<'\n';
}else{
cout << ans <<'\n';
}
}
return ;
}

G. Rikka with Intersections of Paths

题意:

树上给出若干条简单路径,问有多少选k条路径的方案,满足这些路径的交至少有一个点。

题解:

考虑求出LCA,因为树上简单路径至少存在一个交点为至少一条路径的两端点的LCA,同时可以利用树上差分求出有多少条路径经过当前点。

之后计算贡献就行了,但是这里直接计算C(cnt, k)会有重复计算的,我们这里可以考虑刚才关于LCA的性质,求出每个点为多少条路径端点的LCA,个数记为pi,那么最后答案就是C(cnt,k) - C(cnt - pi,k),此时选出的路径中,至少有一条路径的两端点的LCA为当前点,此时就不会重复计算了。因为一条路径的LCA只有一个,我们只会计算经过LCA时的贡献。

代码如下:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 3e5 + , MOD = 1e9 + ;
int T, n, m, k;
struct Edge{
int u,v,next;
}e[N << ];
int head[N],tot;
void adde(int u, int v) {
e[tot].v = v;
e[tot].next = head[u] ;
head[u] = tot++ ;
}
int deep[N], st[N][], sum[N], cnt[N];
ll fac[N], inv[N];
void dfs(int u, int d, int fa) {
st[u][] = fa;
deep[u] = d;
for(int i = head[u]; i != -; i = e[i].next) {
int v = e[i].v;
if(v == fa) continue ;
dfs(v, d + , u);
}
}
ll qp(ll a, ll b) {
ll ans = ;
while(b) {
if(b & ) ans = ans * a % MOD;
a = a * a % MOD;
b >>= ;
}
return ans ;
}
void init() {
for(int i = ; i <= ; i++)
for(int j = ; j <= n ; j++)
st[j][i] = st[st[j][i - ]][i - ];
}
int LCA(int x, int y) {
if(deep[y] > deep[x]) swap(x , y) ;
while(deep[x] != deep[y]) {
int d = deep[x] - deep[y] ;
for(int i = ; i <= ; i++) {
if(d >> i & ) x = st[x][i] ;
}
}
if(x == y) return x ;
for(int i = ; i >= ; i--) {
if(st[x][i] != st[y][i]) {
x = st[x][i] ;
y = st[y][i] ;
}
}
return st[x][] ;
}
void pre(int u, int fa) {
for(int i = head[u] ; i != -; i = e[i].next) {
int v = e[i].v;
if(v == fa) continue ;
pre(v , u);
sum[u] += sum[v] ;
}
}
ll C(ll a ,ll b) {
if(b == || a < b) return ;
return fac[a] * inv[b] % MOD * inv[a - b] % MOD;
}
ll calc(ll x) {
ll ans = C(sum[x], k);
ans = ((ans - C(sum[x] - cnt[x], k) % MOD ) % MOD + MOD ) % MOD;
return ans ;
}
int main() {
ios::sync_with_stdio(false);cin.tie();
fac[] = ;
inv[] = ;
for(int i = ; i < N; i++) {
fac[i] = fac[i - ] * i % MOD;
inv[i] = qp(fac[i] , MOD - ) ;
}
cin >> T;
while(T--) {
memset(head,-,sizeof(head)); tot = ;
cin >> n >> m >> k ;
for(int i = ; i < n ; i++) {
int u, v;
cin >> u >> v;
adde(u, v);adde(v, u);
}
dfs(, , );
init() ;
for(int i = ; i <= m ;i++) {
int u, v;
cin >> u >> v ;
int x = LCA(u , v);
sum[u]++;sum[v]++;
sum[x]--;sum[st[x][]]--;
cnt[x]++;
}
pre(, ) ;
ll ans = ;
for(int i = ; i <= n; i++) {
ans = (ans + calc(i)) % MOD ;
}
cout << ans << '\n' ;
for(int i = ; i <= n ; i++) deep[i] = sum[i] = cnt[i] = ;
}
return ;
}

H. Rikka with A Long Colour Palette

题意:

给出n个区间,k个颜色,现在给区间染色,问怎么染色能使得覆盖有所有颜色的区间长度最大。

题解:

染色过程考虑贪心。我们先按照区间左端点排序,然后依次涂颜色,颜色涂完了之后该怎么涂呢?假设当前左端点为L,并且在之前的区间中,有Ri,Rj,Rk满足Ri < L  < Rj < Rk,那么此时我们涂Ri的颜色肯定是最优的;如果不存在一个Ri,满足L < Ri,这时我们也只需要涂处于最左端的Ri,因为这样可以尽可能地增多所有颜色覆盖的区间长度。

最后就考虑如果计算答案了,将所有点排序后记录左端点为1,右端点为-1,累计前缀和,当和大于等于k时更新答案即可。

代码如下:

#include <bits/stdc++.h>
#define mp make_pair
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N = 2e5 + ;
int T;
int n, k, cnt;
pair<pii,int> a[N << ];
int col[N], has[N], answer[N];
struct Node {
int l, r, id ;
bool operator < (const Node &A) const {
if(l == A.l) return r < A.r;
return l < A.l;
}
}p[N];
int main() {
ios::sync_with_stdio(false);cin.tie();
cin >> T;
while (T--) {
cin >> n >> k;
cnt = ;
for(int i = ; i <= n ; i++) {
int l, r;
cin >> l >> r;
p[i] = Node{l,r,i};
}
if(n < k) {
cout << << '\n' ;
for(int i = ; i < n; i++)
cout << << ' ' ;
cout << << '\n' ;
continue ;
}
sort(p + , p + n + );
priority_queue <pii> q;
for(int i = ; i <= k ; i++) {
q.push(mp(, i)) ;
}
for(int i = ; i <= n ; i++) {
int now = q.top().second;q.pop();
answer[p[i].id] = col[i] = now;
q.push(mp(-p[i].r,now)) ;
}
for(int i = ; i <= n ;i++) {
a[++cnt] = mp(mp(p[i].l,col[i]),) ;
a[++cnt] = mp(mp(p[i].r,col[i]),-) ;
}
sort(a + , a + cnt + ) ;
int ans = , cur = ;
for(int i = ; i <= cnt ; i++) {
if(has[a[i].first.second]) cur--;
has[a[i].first.second] += a[i].second ;
if(has[a[i].first.second]) cur++;
if(cur >= k )
ans += a[i + ].first.first - a[i].first.first;
}
cout << ans << '\n' ;
for(int i = ; i < n ; i++) cout << answer[i] << ' ';
cout << answer[n] << '\n' ;
for(int i = ; i <= k ; i++) has[i] = ;
}
return ;
}

I. Rikka with Sorting Networks

题意:

给出n个数,有k个排序器,每个排序器会使得au < av,即让他们的位置相对有序,问有多少个排列,最后通过这k个排序器后,形成的序列最长上升子序列至少为n - 1。

题解:

满足条件的最长上升子序列个数为(n - 1) ^ 2 + 1个,由于数据范围很小,我们直接构造出来爆搜求解即可。

代码如下:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = ;
int a[N], b[N] ;
int n, k, T, mod;
int from[N], to[N] ;
int ans;
void dfs(int i, int f) {
if(i == ) {
ans += f;
if(ans >= mod) ans -= mod;
return ;
}
if(a[from[i]] < a[to[i]]) {
dfs(i - , f) ;
swap(a[from[i]], a[to[i]]) ;
dfs(i - , f) ;
swap(a[from[i]], a[to[i]]) ;
}
}
int main() {
ios::sync_with_stdio(false);cin.tie();
cin >> T;
while(T--) {
cin >> n >> k >> mod;
for(int i = ; i <= k ; ++i) cin >> from[i] >> to[i] ;
for(int i = ; i <= n ; ++i) a[i] = i ;
ans = ;
dfs(k, ) ;
for(int i = ; i < n ; ++i) {
swap(a[i], a[i + ]);
dfs(k, -);
swap(a[i], a[i + ]);
}
for(int take = ; take <= n ; ++take) {
for(int i = ; i <= n ; ++i) {
if(i == take) continue ;
int cur = ;
for(int j = ; j <= n ; ++j) {
if(cur == take - ) cur++;
if(i == j) a[j] = take ;
else a[j] = ++cur;
}
dfs(k , );
}
}
cout << ans << '\n';
} return ;
}

2018-2019 ACM-ICPC 徐州区域赛 部分题解的更多相关文章

  1. 2015 ACM / ICPC 亚洲区域赛总结(长春站&北京站)

    队名:Unlimited Code Works(无尽编码)  队员:Wu.Wang.Zhou 先说一下队伍:Wu是大三学长:Wang高中noip省一:我最渣,去年来大学开始学的a+b,参加今年区域赛之 ...

  2. 2016 年 ACM/ICPC 青岛区域赛 Problem C Pocky

    昨晚乱入学弟的训练赛,想了一下这个题.推导的过程中,加深了对公理化的概率论理解.$\newcommand{\d}{\mathop{}\!\mathrm{d}}$ 解法一 考虑 $ d < L$ ...

  3. Known Notation括号匹配类问题(2014年ACM/ICPC 亚洲区域赛牡丹江)

    题意: 给你数字或 * 的串,你可以交换一个*和数字.在最前面添1.在一个地方插入*,问你使串满足入栈出栈的(RNP)运算法则. 思路: 引用:https://blog.csdn.net/u01158 ...

  4. Digit sum (第 44 届 ACM/ICPC 亚洲区域赛(上海)网络赛)进制预处理水题

    131072K   A digit sum S_b(n)Sb​(n) is a sum of the base-bb digits of nn. Such as S_{10}(233) = 2 + 3 ...

  5. 2018 ICPC 徐州网络赛

    2018 ICPC 徐州网络赛 A. Hard to prepare 题目描述:\(n\)个数围成一个环,每个数是\(0\)~\(2^k-1\),相邻两个数的同或值不为零,问方案数. solution ...

  6. 2019 ICPC 上海区域赛总结

    2019上海区域赛现场赛总结 补题情况(以下通过率为牛客提交): 题号 标题 已通过代码 通过率 我的状态 A Mr. Panda and Dominoes 点击查看 5/29 未通过 B Prefi ...

  7. 2018.11.25 AMC-ICPC 亚洲区域赛(焦作站)吊银

    11月23日 大清早,跟着wyb的脚步,早起跑过去听方伟的编译原理,然鹅一点都没听进去,在焦作胡辣汤群里疯狂灌水... 听说焦作那边冷得不行,前一天看天气预报说那边已经是2℃了,都快零下了,然鹅学校里 ...

  8. 2016年11月ACM/ICPC亚洲区北京赛赛后总结

    2016年11月12到11月13为期两天的比赛,这是我们这个对第一次去打亚洲区域赛,经过这次比赛,我认识到了自己与别人的差距,也许我们与别人的起点不同,但这不是理由. 这次的比赛12号的热身赛两点开始 ...

  9. 2014ACM/ICPC亚洲区域赛牡丹江站汇总

    球队内线我也总水平,这所学校得到了前所未有的8地方,因为只有两个少年队.因此,我们13并且可以被分配到的地方,因为13和非常大的数目.据领队谁oj在之上a谁去让更多的冠军.我和tyh,sxk,doub ...

随机推荐

  1. day03 作业 and 周末作业

    请输出 name 变量对应的值中 "e" 所在索引位置? # name = "leX leNb"# num = 0# while num < len(na ...

  2. leetcode27_C++Remove Element

    给定一个数组 nums 和一个值 val,你需要原地移除所有数值等于 val 的元素,返回移除后数组的新长度. 不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成 ...

  3. Python Fileinput 模块介绍

    作者博文地址:http://www.cnblogs.com/spiritman/ fileinput模块提供处理一个或多个文本文件的功能,可以通过使用for循环来读取一个或多个文本文件的所有行. [默 ...

  4. ntp时钟服务器配置

    集群中时间不同步有可能会让大数据的应用程序运行混乱,造成不可预知的问题,比如Hbase,当时间差别过大时就会挂掉,所以在大数据集群中,ntp服务,应该作为一种基础的服务,以下在演示在CentOS 7. ...

  5. 多源最短路——Floyd算法

    Floyd算法 问题的提出:已知一个有向网(或者无向网),对每一对定点vi!=vj,要求求出vi与vj之间的最短路径和最短路径的长度. 解决该问题有以下两种方法: (1)轮流以每一个定点为源点,重复执 ...

  6. OpenCV学习笔记——图像平滑处理

    1.blur 归一化滤波器Blurs an image using the normalized box filter.C++: void blur(InputArray src, OutputArr ...

  7. 3dContactPointAnnotationTool开发日志(二九)

      今天想着在Windows平台上跑通那个代码,不过它的官网上写的支持平台不包括windows,但我还是想试试,因为看他的依赖好像和平台的关系不是特别大.   看了下它的py代码,不知道是py2还是p ...

  8. QLayout窗口布局

    版权声明:若无来源注明,Techie亮博客文章均为原创. 转载请以链接形式标明本文标题和地址: 本文标题:QLayout窗口布局     本文地址:http://techieliang.com/201 ...

  9. 【leetcode】215. Kth Largest Element in an Array

    Find the kth largest element in an unsorted array. Note that it is the kth largest element in the so ...

  10. elasticsearch6 学习之批量操作

    环境:elasticsearch6.1.2        kibana6.1.2  一.mget批量查询 mget可以将多个请求才能获的数据,合并到一个请求中以节省网络开销. 1.查询同一个索引下,通 ...