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. frame pointer及其用途

    1 什么是frame pointer frame pointer指向本函数栈帧顶,通过它可以找到本函数在进程栈中的位置.有专门的寄存器保存该值. 2 frame pointer有什么用 主要是back ...

  2. Bing必应地图中国API入门讲座之八:显示驾车路线

    Bing必应地图中国API入门讲座之八:显示驾车路线 2011-05-24 14:47:36|  分类: Bing&Google|字号 订阅     这篇文章非常值得纪念,因为我是在Googl ...

  3. 洛谷 P1181,1182 数列分段Section

    数列分段Section I 题目描述 对于给定的一个长度为N的正整数数列A[i],现要将其分成连续的若干段,并且每段和不超过M(可以等于M),问最少能将其分成多少段使得满足要求. 输入输出格式 输入格 ...

  4. GCD总结(一)

    GCD为我们提供了三种类型的调度队列(dispatch queue),分别为串行,并行和主调度队列. 串行(Serial)     你可以创建任意个数的串行队列,每个队列依次执行添加的任务,一个队列同 ...

  5. apache相关补充

    apache相关补充 sendfile机制 1)不用sendfile的传统网络传输过程: read(file, tmp_buf, len) write(socket, tmp_buf, len) 2) ...

  6. P3626 [APIO2009]会议中心

    传送门 好迷的思路-- 首先,如果只有第一问就是个贪心,排个序就行了 对于第二问,我们考虑这样的一种构造方式,每一次都判断加入一个区间是否会使答案变差,如果不会的话就将他加入别问我正确性我不会证 我们 ...

  7. mybatis编写mapper操作

    mybatis编写mapper resultType和resultMap resultType可以直接指定返回类型,例如自定义的bean  <!--通过账号查询用户:一个参数用parameter ...

  8. vue-router+webpack线上部署时单页项目路由,刷新页面出现404问题

    使用vue项目,线上部署的时候,访问首页以及通过路由打开二级页面没有问题,但是一刷新就出现404现象 因为刷新页面时访问的资源在服务端找不到,因为vue-router设置的路由不是真实存在的路径. 解 ...

  9. 二分搜索 HDOJ 2289 Cup

    题目传送门 /* 二分搜索:枚举高度,计算体积与给出的比较. */ #include <cstdio> #include <algorithm> #include <cs ...

  10. RHEL5.6更新yum源

    RHEL5.6更新yum源记录,2017年2月20日 root用户切换目录至:/etc/yum.repos.d/ [root@localhost yum.repos.d]# pwd /etc/yum. ...