Solved:3

rank:195

F. take

官方题解:小 A 在打开第 i 个箱子后会交换手中的钻石和第 i 个箱子中的钻石

当且仅当第 i个箱子的钻石是前 i 个箱子打开后出现的所有钻石里最大的。

那么要算概率的话,前面箱子中钻石大于等于它的打开后就不能有钻石
用树状数组维护一下

线段树(不会树状数组) 调了半天居然快速幂忘记写返回了

#include <stdio.h>
#include <algorithm>
#include <iostream>
#include <string.h>
using namespace std;
typedef long long ll;
const ll mod = ; ll sum[];
int num[]; ll pow_mod(ll x, ll y)
{
ll res = ;
while(y)
{
if(y & ) res = res * x % mod;
y >>= ;
x = x * x % mod;
}
return res;
} struct node
{
int p, d, id;
}E[]; bool cmp1(node A, node B)
{
return A.d < B.d;
} bool cmp2(node A, node B)
{
return A.id < B.id;
} void pushup(int rt)
{
sum[rt] = sum[rt << ] * sum[rt << | ] % mod;
} void build(int l, int r, int rt)
{
if(l == r)
{
sum[rt] = ;
return;
} int m = l + r >> ;
build(l, m, rt << );
build(m + , r , rt << | );
pushup(rt);
} void update(int k, ll v, int l, int r, int rt)
{
if(l == r)
{
sum[rt] = v;
return;
} int m = l + r >> ;
if(k <= m) update(k, v, l, m, rt << );
else update(k, v, m + , r, rt << | );
pushup(rt);
} ll query(int ql, int qr, int l, int r, int rt)
{
if(ql <= l && qr >= r) return sum[rt]; ll res = ;
int m = l + r >> ;
if(ql <= m) res = res * query(ql, qr, l, m, rt << ) % mod;
if(qr > m) res = res * query(ql, qr, m + , r, rt << | ) % mod;
return res;
} int main()
{
int n;
scanf("%d", &n);
ll ny = pow_mod(, mod - );
for(int i = ; i <= n; i++)
{
scanf("%d%d", &E[i].p, &E[i].d);
E[i].id = i;
E[i].p = - E[i].p;
}
sort(E + , E + + n, cmp1);
for(int i = ; i <= n; i++) num[E[i].id] = i;
sort(E + , E + + n, cmp2);
build(, n, ); ll ans = ;
for(int i = ; i <= n; i++)
{
int v = num[E[i].id];
ans = (ans + query(v, n, , n, ) * ( - E[i].p) % mod * ny % mod) % mod;
update(v, E[i].p * ny % mod, , n, );
}
printf("%lld\n", ans);
return ;
}

H. subseq

题意:找一个字典序第k小的合法b数组 使得以b数组的大小作为下标的a数组是严格上升的子序列

题解:用f(i)表示从第i个元素做为起始能组成的上升子序列个数

跃然纸上的转移 f(i) = 1 + ∑f(j) (i < j <= n && a(j) > a(i)) 这个用树状数组维护就好了

离散好以后 从大到小的插入就可以

然后贪心的从1枚举 在满足这个点a(i)大于上一个插入答案中的点的情况下

如果f(i) >= k就意味着这个点可以做为答案中的一位 k-- 就少了后面什么都不接的一种

如果f(i) < k 表示这个点显然不做为答案中的一位 k -= f[i] 把这些字典序比他小的答案全减去

还有个很坑的地方就是可能会爆ll 但是问的k只有1e18 所以判一下上界 用我的写法用后缀和比较好

#include <bits/stdc++.h>
using namespace std;
typedef long long ll; int n;
ll k;
struct node
{
int val, id, v;
}a[];
ll c[];
ll f[];
int ans[]; bool cmp(node A, node B) {return A.val < B.val;}
bool cmp1(node A, node B) {return A.id < B.id;}
inline void add(int x, ll v)
{
for( ; x > ; x -= x & -x)
{
c[x] += v;
if(c[x] > 1e18) c[x] = 1e18;
}
}
inline ll ask(int x)
{
ll res = ;
for( ; x <= n; x += x & -x)
{
res += c[x];
if(res > 1e18) res = 1e18;
}
return res;
} int main()
{
scanf("%d%lld", &n, &k);
for(int i = ; i <= n; i++) scanf("%d", &a[i].val), a[i].v = a[i].val, a[i].id = i;
sort(a + , a + + n, cmp); a[].val = ;
for(int i = ; i <= n; i++)
{
if(a[i].val == a[i - ].v) a[i].val = a[i - ].val;
else a[i].val = a[i - ].val + ;
}
sort(a + , a + + n, cmp1); for(int i = n; i >= ; i--)
{
//f[i] = ask(n) - ask(a[i].val * 1LL) + 1LL;
//这样写会wa 因为两个都很大的情况下 返回1e18 但是一减去就没了
f[i] = ask(a[i].val + ) + ;
add(a[i].val, f[i]);
} int cnt = ;
for(int i = ; i <= n; i++)
{
if(!k) break;
if(a[i].val > a[ans[cnt]].val)
{
if(f[i] >= k) ans[++cnt] = i, k--;
else k -= f[i];
}
}
if(k) puts("-1");
else
{
printf("%d\n", cnt);
for(int i = ; i < cnt; i++) printf("%d ", ans[i]);
printf("%d\n", ans[cnt]);
}
return ;
}

I. vcd

题意:n个点 定义一个集合是好的为 对于这个集合的任意一个子集 以右开口的矩形把他包起来 不会包含这个子集的其他点

   求有多少个好的集合

题解:考虑一个点的话显然都满足

考虑两个点的话显然纵坐标相同的不满足情况 那么统计答案就减去纵坐标相同的

考虑三个点的话显然是满足像小于符号的点才行(好像不是很显然 但是多画几种情况就看出来了)

统计答案就是对于每个点 在比这个点横坐标大的情况下 在他上面的点 x 在他下面的点 且任意两个点横坐标不能相同

所以我们用树状数组维护y 再按x从大到小的插入 对于相同的x 都统计完答案后再一起插入

考虑四个点的话是找不到答案的 简单的证明一下 对于一个像红对勾形状的三个点

假设再加入一个点要满足答案 那么新加入的点和任意两个点都能组成小于号

对于右边两个点 要组成小于号 要在下面哪个点下面

对于左边两个点 要组成小于号 要在上面哪个点上面 这显然是矛盾的

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod = ; ll n;
struct node
{
int x, y, pre;
}p[];
int b[];
ll vis[];
ll c[]; bool cmp1(node A, node B) {return A.y < B.y;}
bool cmp2(node A, node B) {return A.x < B.x;}
inline void add(int x) {for( ; x <= n; x += x & -x) c[x]++;}
inline ll ask(int x) {ll res = ; for( ; x > ; x -= x & -x) res += c[x], res %= mod; return res;} int main()
{
scanf("%lld", &n);
for(int i = ; i <= n; i++) scanf("%d%d", &p[i].x, &p[i].y), p[i].pre = p[i].y;
sort(p + , p + + n, cmp1); p[].y = ; vis[]++; //这沙雕地方卡了一晚上 写昏了
for(int i = ; i <= n; i++)
{
if(p[i].y == p[i - ].pre) p[i].y = p[i - ].y;
else p[i].y = p[i - ].y + ;
vis[p[i].y]++;
}
sort(p + , p + + n, cmp2); ll ans = ;
ans += 1LL * n + n * (n - 1LL) / 2LL;
for(int i = ; i <= n; i++) ans -= vis[i] * (vis[i] - ) / ;
ans %= mod; int now = n;
for(int i = n; i >= ; i--)
{
ll tmp1 = ask(n) - ask(p[i].y);
ll tmp2 = ask(p[i].y - );
ans += tmp1 * tmp2 % mod;
ans %= mod; if(p[i].x != p[i - ].x)
{
for(int j = now; j >= i; j--) add(p[j].y);
now = i - ;
}
}
printf("%lld\n", ans);
return ;
}

牛客多校Round 5的更多相关文章

  1. 牛客多校Round 10

    咕咕咕.... 去烽火台和兵马俑了

  2. 牛客多校Round 9

    Solved:1 rank:112 E. Music Game 题解说有个非简化的原题 bzoj4318 #include <bits/stdc++.h> using namespace ...

  3. 牛客多校Round 8

    Solved:2 rank:164 签了两个oeis,但这样真的开心嘛

  4. 牛客多校Round 6

    Solved:3 rank:156 J. Heritage of skywalker 学习一下nth_element 可以o (n)的找出前多少大的元素 #include <bits/stdc+ ...

  5. 牛客多校Round 4

    Soved:3 rank:133 A.Ternay String 欧拉降幂一下 但是反复求phi会超时 但mod是同一个就可以记忆化一下 #include <bits/stdc++.h> ...

  6. 牛客多校Round 3

    Solved:2 rank:306 跑路场..... A.PACM team 简单背包记录路径都写挂 退役算了 #include <bits/stdc++.h> using namespa ...

  7. 牛客多校Round 2

    Solved:3 rank:187 H.travel 题意:给一颗带有点权的树 找三条不相交的链 使得点权最大 题解:使用树形DP dp[x][i][0/1] 表示x节点选择i条链 有没有经过x的链 ...

  8. 牛客多校Round 1

    Solved:1 rank:249 E. Removal dp i,j表示前i个数删除了j个且选择了第i个的答案 类似字符串的dp 预处理一下nex i_k即i后面k第一次出现的位置  就好转移了 # ...

  9. 2019牛客多校第一场 I Points Division(动态规划+线段树)

    2019牛客多校第一场 I Points Division(动态规划+线段树) 传送门:https://ac.nowcoder.com/acm/contest/881/I 题意: 给你n个点,每个点有 ...

随机推荐

  1. 通过java类文件识别JDK编译版本号

    类文件里第5,6.7,8四个字节是jDK版本信息.当中5,6为小版本:7,8为大版本. 大版本号号相应JDK版本号例如以下: JDK版本 7,8字节 JDK8 52(0x34) JDK7 51(0x3 ...

  2. 中文分词实践(基于R语言)

    背景:分析用户在世界杯期间讨论最多的话题. 思路:把用户关于世界杯的帖子拉下来.然后做中文分词+词频统计,最后将统计结果简单做个标签云.效果例如以下: 兴许:中文分词是中文信息处理的基础.分词之后.事 ...

  3. ArcGIS中生成蜂窝多边形算法解析

    近来有不少同学.都有问我关于蜂窝多边形的问题.也就是正六边形,也就是以下这个东东: 一般的问答模式例如以下: 亲们问:ArcGIS里面那个工具能够做这个东东? 虾神答:额,没有原生的工具. 亲们问:那 ...

  4. PNG vs. GIF vs. JPEG vs. SVG - When best to use?

    image - PNG vs. GIF vs. JPEG vs. SVG - When best to use? - Stack Overflow https://stackoverflow.com/ ...

  5. socket listen backlog

    http://stackoverflow.com/questions/4253454/question-about-listening-and-backlog-for-sockets The list ...

  6. hdu 5074 Hatsune Miku DP题目

    题目传送门http://acm.hdu.edu.cn/showproblem.php?pid=5074 $dp[i][j] =$ 表示数列前$i$个数以$j$结尾的最大分数 $dp[i][j] = - ...

  7. 4.7.4 Constructing LALR Parsing Tables

    4.7.4 Constructing LALR Parsing Tables We now introduce our last parser construction method, the LAL ...

  8. BADI FCODE(菜单) 增强

    菜单增强功能只能用于非依赖于过滤器的一次性BADI(不是多用途的). 目前,菜单增强功能只能与程序增强功能(界面)一起创建. 定义一个没有过滤器的一次性增强 2.Classic Badi在FCODE ...

  9. LOJ#503. 「LibreOJ β Round」ZQC 的课堂(容斥+FHQTreap)

    题面 传送门 题解 首先\(x\)和\(y\)两维互相独立,可以分开考虑,我们以\(x\)为例 我们把\(x\)做个前缀和,那么就是问有多少\(i\)满足\(s_is_{i-1}<0\),其中\ ...

  10. [C++ STL] 迭代器(iterator)详解

    背景:指针可以用来遍历存储空间连续的数据结构,但是对于存储空间非连续的,就需要寻找一个行为类似指针的类,来对非数组的数据结构进行遍历.因此,我们引入迭代器概念.   一.迭代器(iterator)介绍 ...