Solved:5

Rank:296

E Find the median (线段树)

题意:最开始一个空的数组 4e5次操作 每次把Li,Ri中的每个数插入进来 问当前的中位数

题解:把这n个区间离散化去重以后 剩下m个点 可以分成m-1个连续的区间

   有个巧妙的方法是把所有的右端点+1后 每两个点之间表示一个左闭右开的区间

   然后线段树每个叶子节点就表示这个区间的信息 每次操作就是先区间更新再查询了

   用la表示这个区间被覆盖了多少次 查询的时候类似整体二分 其实还可以维护一个叶子节点表示的区间长度

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 4e5 + 5; int n, cnt;
int a1, b1, c1, m1;
int a2, b2, c2, m2;
int x[MAXN], y[MAXN];
int p[MAXN << 1], L[MAXN], R[MAXN];
ll pre[MAXN << 1]; ll sum[MAXN << 5];
int la[MAXN << 5];
int lz[MAXN << 5];
void pushup(int rt) {
sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
} void pushdown(int l, int r, int rt) {
if(lz[rt]) {
lz[rt << 1] += lz[rt];
lz[rt << 1 | 1] += lz[rt];
la[rt << 1] += lz[rt];
la[rt << 1 | 1] += lz[rt];
int mid = l + r >> 1;
sum[rt << 1] += 1LL * lz[rt] * (pre[mid] - pre[l - 1]);
sum[rt << 1 | 1] += 1LL * lz[rt] * (pre[r] - pre[mid]);
lz[rt] = 0;
}
} void update(int ql, int qr, int l, int r, int rt) {
if(ql <= l && qr >= r) {
lz[rt]++; la[rt]++;
sum[rt] += pre[r] - pre[l - 1];
return;
}
pushdown(l, r, rt); int mid = l + r >> 1;
if(ql <= mid) update(ql, qr, l, mid, rt << 1);
if(qr > mid) update(ql, qr, mid + 1, r, rt << 1 | 1);
pushup(rt);
} int query(int l, int r, int rt, ll k) {
if(l == r) return p[l] + (k - 1) / la[rt];
pushdown(l, r, rt); int mid = l + r >> 1;
if(sum[rt << 1] >= k) return query(l, mid, rt << 1, k);
else return query(mid + 1, r, rt << 1 | 1, k - sum[rt << 1]);
} int main() {
cnt = 0;
scanf("%d", &n);
scanf("%d%d%d%d%d%d", &x[1], &x[2], &a1, &b1, &c1, &m1);
scanf("%d%d%d%d%d%d", &y[1], &y[2], &a2, &b2, &c2, &m2);
for(int i = 3; i <= n; i++) {
x[i] = (1LL * a1 * x[i - 1] + 1LL * b1 * x[i - 2] + 1LL * c1) % m1;
y[i] = (1LL * a2 * y[i - 1] + 1LL * b2 * y[i - 2] + 1LL * c2) % m2;
}
for(int i = 1; i <= n; i++) {
L[i] = min(x[i], y[i]) + 1;
R[i] = max(x[i], y[i]) + 2;
p[++cnt] = L[i], p[++cnt] = R[i];
}
sort(p + 1, p + 1 + cnt);
cnt = unique(p + 1, p + 1 + cnt) - p - 1;
p[cnt + 1] = p[cnt]; for(int i = 1; i <= cnt; i++) pre[i] = pre[i - 1] + 1LL * (p[i + 1] - p[i]); ll tot = 0;
for(int i = 1; i <= n; i++) {
int t1 = lower_bound(p + 1, p + 1 + cnt, L[i]) - p;
int t2 = lower_bound(p + 1, p + 1 + cnt, R[i]) - p - 1;
update(t1, t2, 1, cnt, 1);
tot += 1LL * (R[i] - L[i]); //左闭右开
printf("%d\n", query(1, cnt, 1, (tot + 1LL) / 2LL));
}
return 0;
}

E Find the median

F Energy Stones

题意:n个石头 初始能量Ei 每秒能量增长Li 最多能量Ci

   有m次收割操作 每次选择一个时间点 将区间L,R内的石头能量都吸收 求最后一共吸收了多少能量

题解:因为他是问的最后一共吸收了多少能量 不是问的每一次

   所以我们可以考虑每一个石头对答案产生了多少贡献

   对于每一个石头 这m次收割只有部分收割到了它 假设收割了k次

   如果我们知道了这k个时间点 除去第一个特判以外 每两个时间点之间会产出一次贡献

   贡献要么是Ci 要么是Li*区间长度

   对于n个石头 被收割的时间点有许多重复的 所以我们用set维护收割的时间点

   在枚举到到第L个石头的时候把时间点插入进set 在枚举到底R + 1个石头的时候 删除这个时间点

   然后一个树状数组维护长度为i的区间个数 一个树状数组维护长度为i的区间 长度和

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 1e5 + 5; int n, m;
int E[MAXN], L[MAXN], C[MAXN];
ll a[MAXN << 1], b[MAXN << 1];
vector<int> g[MAXN];
set<int> st; ll query1(int x) {
ll res = 0;
for(int i = x; i; i -= (i & -i)) res += a[i];
return res;
} ll query2(int x) {
ll res = 0;
for(int i = x; i; i -= (i & -i)) res += b[i];
return res;
} void add(int x, int val) {
for(int i = x; i <= 200001; i += (i & -i)) {
if(val > 0) a[i]++;
else a[i]--;
b[i] += 1LL * val;
}
} void inser(int x) {
if(st.empty()) {
st.insert(x);
return;
} auto pos = st.lower_bound(x);
if(pos == st.begin()) {
int t = (*pos) - x;
add(t, 1LL * t);
} else if(pos == st.end()) {
int t = x - (*(prev(pos)));
add(t, 1LL * t);
} else {
int t1 = x - (*(prev(pos)));
int t2 = (*pos) - x;
add(t1, 1LL * t1); add(t2, 1LL * t2);
add(t1 + t2, 1LL * (-t1 - t2));
}
st.insert(x);
} void del(int x) {
auto pos = st.find(x);
if(st.size() == 1) {
st.erase(pos);
return;
}
if(pos == st.begin()) {
int t = (*(next(pos))) - x;
add(t, 1LL * -t);
} else if(pos == prev(st.end())) {
int t = x - (*(prev(pos)));
add(t, 1LL * -t);
} else {
int t1 = x - (*(prev(pos)));
int t2 = (*(next(pos))) - x;
add(t1, 1LL * -t1); add(t2, 1LL * -t2);
add(t1 + t2, 1LL * (t1 + t2));
}
st.erase(pos);
} int main() {
int T;
scanf("%d", &T);
int cas = 0;
while(T--) {
st.clear();
ll ans = 0;
scanf("%d", &n);
for(int i = 1; i <= n; i++) scanf("%d%d%d", &E[i], &L[i], &C[i]);
for(int i = 1; i <= n + 1; i++) g[i].clear();
memset(a, 0, sizeof(a)); memset(b, 0, sizeof(b)); scanf("%d", &m);
for(int i = 1; i <= m; i++) {
int t, l, r; scanf("%d%d%d", &t, &l, &r);
g[l].push_back(t);
g[r + 1].push_back(-t);
} for(int i = 1; i <= n; i++) {
for(int j = 0; j < g[i].size(); j++) {
if(g[i][j] > 0) inser(g[i][j]);
else del(-g[i][j]);
} if(st.empty()) continue;
ans += min(1LL * C[i], 1LL * E[i] + 1LL * (*st.begin()) * L[i]);
if(L[i] == 0) continue;
int len = C[i] / L[i];
ans += 1LL * query2(len) * L[i];
ans += 1LL * C[i] * (st.size() - query1(len) - 1);
}
printf("Case #%d: %lld\n", ++cas, ans);
}
return 0;
}

F Energy stones

H pair

题意:给三个数a,b,c 求有多少对数满足 x & y > c || x ^ y < c x的范围在1-a y的范围在1-b;

题解:第一次写这种两个范围的数位DP.. 需要存的状态有

   当前枚举到pos位 And=0表示x&y和c的大小不确定 1表示x&y已经大于c 2表示已经小于

   Xor同理 然后存一下当前枚举两个数卡到的边界

   因为数位dp是从0开始统计的 还多统计了0^y(y<c) 和x^0(x<c) 的答案  所以还要减去

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int a, b, c;
ll dp[35][3][3][2][2]; ll dfs(int pos, int And, int Xor, int sj1, int sj2) {
if(pos == -1) {
if(And == 1 || Xor == 1) return 1;
else return 0;
}
if(dp[pos][And][Xor][sj1][sj2] != -1) return dp[pos][And][Xor][sj1][sj2]; ll res = 0;
int up1 = sj1 ? (a >> pos & 1) : 1;
int up2 = sj2 ? (b >> pos & 1) : 1; for(int i = 0; i <= up1; i++)
for(int j = 0; j <= up2; j++) {
int tand = And;
int txor = Xor;
if(tand == 0) {
if((i & j) > (c >> pos & 1)) tand = 1;
else if((i & j) < (c >> pos & 1)) tand = 2;
}
if(txor == 0) {
if((i ^ j) < (c >> pos & 1)) txor = 1;
else if((i ^ j) > (c >> pos & 1)) txor = 2;
}
res += dfs(pos - 1, tand, txor, sj1 && (i == up1), sj2 && (j == up2));
}
dp[pos][And][Xor][sj1][sj2] = res;
return res;
} int main() {
memset(dp, -1, sizeof(dp)); int T;
scanf("%d", &T);
while(T--) {
memset(dp, -1, sizeof(dp));
scanf("%d%d%d", &a, &b, &c);
printf("%lld\n", dfs(31, 0, 0, 1, 1) - min(a, c - 1) - min(b, c - 1) - 1);
}
return 0;
}

H pair

I Chessbord

题意:给出n,m 问构造一个k*k的矩阵 矩阵每个元素不小于m

   且从每一行选一个数 且这k个数的属于不同的列 方案数

题解:枚举矩阵大小k 再枚举选出的k个元素的和j 为了计算方便 这个j等于实际的和减去k*m 那么元素大小可为0

   我们发现合法的方案一定长这个样子 假定k为3

   a1+b1  a2+b1  a3+b1

   a1+b2  a2+b2  a3+b2

   a1+b3  a2+b3  a3+b3

   这样我们随便选出的和一定都等于a1+a2+a3+b1+b2+b3 这就是我们枚举的和j

   这个方案数就等于C(j+2*k-1,2*k-1) 因为元素可以为0 那么我们让这2k项每个都先+1 分配完了再-1

   等价于从j+2*k-1个空位中插2*k-1个板子 当然这样计算是有重复的

   重复是因为假如让a1,a2,a3都加1 b1,b2,b3都减1 只要b都非负 这个方案是一样的 但是也计数了

   所以我们就要减去b1,b2,b3都大于0的情况了 那么就等于让k项都+1 分配完了再-1

   综上所述 一次枚举的方案数=C(j+2*k-1,2*k-1) - C(j+k-1,2*k-1)

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod = 998244353;
ll jc[5005], ny[5005];
ll n, m; ll pow_mod(ll x, ll y) {
ll res = 1;
while(y) {
if(y & 1) res = res * x % mod;
x = x * x % mod;
y >>= 1;
}
return res;
} ll C(ll x, ll y) {
if(x < 0 || y < 0 || x < y) return 0;
return jc[x] * ny[y] % mod * ny[x - y] % mod;
} int main() {
jc[0] = 1LL;
for(ll i = 1; i <= 5000; i++) jc[i] = jc[i - 1] * i % mod;
ny[5000] = pow_mod(jc[5000], mod - 2);
for(ll i = 4999; i >= 0; i--) ny[i] = ny[i + 1] * (i + 1) % mod; int T;
scanf("%d", &T);
while(T--) {
scanf("%lld%lld", &n, &m);
ll ans = 0;
for(ll i = 1; i <= n; i++) {
if(i * m > n) break;
for(ll j = 0; j <= n; j++) {
if(i * m + j > n) break;
ans += C(j + 2 * i - 1, 2 * i - 1) - C(j + i - 1, 2 * i - 1);
ans %= mod;
}
}
printf("%lld\n", (ans + mod) % mod);
}
return 0;
}

I Chessbord

2019牛客多校 Round7的更多相关文章

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

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

  2. 2019牛客多校第二场 A Eddy Walker(概率推公式)

    2019牛客多校第二场 A Eddy Walker(概率推公式) 传送门:https://ac.nowcoder.com/acm/contest/882/A 题意: 给你一个长度为n的环,标号从0~n ...

  3. 2019牛客多校第八场 F题 Flowers 计算几何+线段树

    2019牛客多校第八场 F题 Flowers 先枚举出三角形内部的点D. 下面所说的旋转没有指明逆时针还是顺时针则是指逆时针旋转. 固定内部点的答案的获取 anti(A)anti(A)anti(A)或 ...

  4. 2019牛客多校 Round4

    Solved:3 Rank:331 B xor 题意:5e4个集合 每个集合最多32个数 5e4个询问 询问l到r个集合是不是都有一个子集的xor和等于x 题解:在牛客多校第一场学了线性基 然后这个题 ...

  5. 2019牛客多校第一场E ABBA(DP)题解

    链接:https://ac.nowcoder.com/acm/contest/881/E 来源:牛客网 ABBA 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 524288K,其他语 ...

  6. 2019牛客多校第四场 I题 后缀自动机_后缀数组_求两个串de公共子串的种类数

    目录 求若干个串的公共子串个数相关变形题 对一个串建后缀自动机,另一个串在上面跑同时计数 广义后缀自动机 后缀数组 其他:POJ 3415 求两个串长度至少为k的公共子串数量 @(牛客多校第四场 I题 ...

  7. 2019牛客多校第四场 A meeting

    链接:https://ac.nowcoder.com/acm/contest/884/A来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 524288K,其他语言10485 ...

  8. [2019牛客多校第二场][G. Polygons]

    题目链接:https://ac.nowcoder.com/acm/contest/882/G 题目大意:有\(n\)条直线将平面分成若干个区域,要求处理\(m\)次询问:求第\(q\)大的区域面积.保 ...

  9. 2019 牛客多校第一场 D Parity of Tuples

    题目链接:https://ac.nowcoder.com/acm/contest/881/D 看此博客之前请先参阅吕凯飞的论文<集合幂级数的性质与应用及其快速算法>,论文中很多符号会被本文 ...

随机推荐

  1. .netcore 急速接入第三方登录,不看后悔

    新年新气象,趁着新年的喜庆,肝了十来天,终于发了第一版,希望大家喜欢. 如果有不喜欢看文字的童鞋,可以直接看下面的地址体验一下: https://oauthlogin.net/ 前言 此次带来得这个小 ...

  2. 【SpringBoot1.x】SpringBoot1.x 入门

    SpringBoot1.x 入门 文章源码 简介 传统的 JavaEE 开发,十分笨重且配置繁琐,开发效率很低,而且有很复杂的部署流程,对于第三方技术的集成也很困难. Sring 全家桶时代则解决了上 ...

  3. 【Linux】扩大swap分区

    今天安装oracle的时候,提示我swap分区过小.需要最少3g以上 但是安装系统了,想要扩大swap分区怎么办呢 下面来介绍如何扩大swap分区 按步骤介绍 Red Hat linux 如何增加sw ...

  4. 环境变量IFS

    环境变量IFS的值是由1个空格.1个制表符.1个换行符依序构成的字符串,也就是" \t\n"字符串. #查看IFS变量值的长度: test ~ # expr length &quo ...

  5. 这难道不是.NET5 的bug? 在线求锤?

    hello,最近在对一个使用.NET5项目的认证授权系统进行重构,对.NET 5的授权中间件的源码有些看法. 也希望同学们能帮我理解. 一个朴素的需求 这是一个api项目,默认所有的api都需要授权, ...

  6. Job for docker.service failed because start of the service was attempted too often. See "systemctl status docker.service" and "journalctl -xe" for details. To force a start use "systemctl reset-failed

    安装docker时,自己添加了国内的hub.docker.com镜像 [root@ce-docker ~]# systemctl restart docker 出现以下报错:Job for docke ...

  7. ORACLE 归档日志打开关闭方法(转载)

    一 设置为归档方式 1 sql> archive log list; #查看是不是归档方式 2 sql> alter system set log_archive_start=true s ...

  8. js实现简单的俄罗斯方块小游戏

    js实现简单的俄罗斯方块小游戏 开始 1. 创建一个宽为 200px,高为 360px 的背景容器 <!DOCTYPE html> <html lang="en" ...

  9. 全栈性能测试修炼宝典-JMeter实战笔记(一)

    了解性能测试 性能测试不仅能够定位.分析问题,还要把握系统性能变化趋势:性能测试工程师能够帮助解决性能问题,搞定测试过程中的各种不合理配置,给出专业的优化建议. 第一章 性能方向职业发展 软件测试职业 ...

  10. (06)-Python3之--判断、循环

    1.判断(if) 语法: if 条件(True/False): 条件为真时,执行的代码(要干的事情)[elif 条件: 条件为真时,执行的代码(要干的事情)elif 条件: 条件为真时,执行的代码(要 ...