T1 [JZOJ2908] 矩阵乘法

题目描述

  给你一个 N*N 的矩阵,不用算矩阵乘法,但是每次询问一个子矩形的第 K 小数。

数据范围

  对于 $20\%$ 的数据,$N \leq 100$,$Q \leq 10^3$

  对于 $40\%$ 的数据,$N \leq 300$,$Q \leq 10^4$

  对于 $60\%$ 的数据,$N \leq 400$,$Q \leq 3 \times 10^4$

  对于 $100\%$ 的数据,$N \leq 500$,$Q \leq 6 \times 10^4$

分析

  作为一个数据结构菜鸡怎么可能会做这种题目

  本题有多种写法我都写不来,代码中给出是二维树状数组+整体二分,此外还有主席树+分块没学过啊,等等

  基于划分树的边二分边查询的思想,我们可以二分所有询问,一开始二分同样的一个数值,即查询一个子矩形中小于等于 $mid$ 的数的个数,这里用二维树状数组进行统计

  二分后所有节点会分成两边,只需要将所有询问与矩阵中的数字分别递归即可

  时间复杂度为 $O((q+n^2) \, log^2 n \, log \, q)$

  实际上由于二维树状数组的常数非常小,所以这个算法是可以通过的

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
#define inf 0x3f3f3f3f
#define N 502
#define M 60005 inline int read() {
int x = , f = ; char ch = getchar();
while (!isdigit(ch)) {if (ch == '-') f = -; ch = getchar();}
while ( isdigit(ch)) {x = x * + ch - ''; ch = getchar();}
return x *= f;
} int n, m, t[N][N];
int id[M], cur[M], ans[M], q1[M], q2[M]; struct Mat {int x, y, v;} g[N * N];
bool cmp(Mat a, Mat b) {return a.v < b.v;}
struct Query {int x1, y1, x2, y2, k;} q[M]; inline int lowbit(int x) {return x & -x;} inline void add(int x, int y, int v) {
for (int i = x; i <= n; i += lowbit(i))
for (int j = y; j <= n; j += lowbit(j))
t[i][j] += v;
} inline int pre(int x, int y) {
int sum = ;
for (int i = x; i; i -= lowbit(i))
for (int j = y; j; j -= lowbit(j))
sum += t[i][j];
return sum;
} inline int sub(int x1, int y1, int x2, int y2) {
int sum = pre(x2, y2);
sum -= pre(x1 - , y2) + pre(x2, y1 - );
sum += pre(x1 - , y1 - );
return sum;
} void solve(int l, int r, int ql, int qr) {
if (ql > qr) return;
if (l == r) {
for (int i = ql; i <= qr; i++) ans[id[i]] = g[l].v;
return;
}
int mid = (l + r) >> , cnt1 = , cnt2 = ;
for (int i = l; i <= mid; i++) add(g[i].x, g[i].y, );
for (int i = ql, j = id[i]; i <= qr; j = id[++i]) {
int sum = cur[j] + sub(q[j].x1, q[j].y1, q[j].x2, q[j].y2);
if (sum >= q[j].k) q1[++cnt1] = j;
else q2[++cnt2] = j, cur[j] = sum;
}
int cnt = ql - ;
for (int i = ; i <= cnt1; i++) id[++cnt] = q1[i];
for (int i = ; i <= cnt2; i++) id[++cnt] = q2[i];
for (int i = l; i <= mid; i++) add(g[i].x, g[i].y, -);
solve(l, mid, ql, ql + cnt1 - );
solve(mid + , r, ql + cnt1, qr);
} int main(){
n = read(); m = read();
for (int i = ; i <= n; i++)
for (int j = ; j <= n; j++) {
g[(i - ) * n + j].x = i;
g[(i - ) * n + j].y = j;
g[(i - ) * n + j].v = read();
}
sort(g + , g + n * n + , cmp);
for (int i = ; i <= m; i++) {
q[i].x1 = read(); q[i].y1 = read();
q[i].x2 = read(); q[i].y2 = read();
q[i].k = read(); id[i] = i;
}
solve(, n * n, , m);
for (int i = ; i <= m; i++)
printf("%d\n", ans[i]); return ;
}

T2 [JZOJ3410] Tree

题目描述

  Wayne 在玩儿一个很有趣的游戏。在游戏中,Wayne 建造了 N 个城市,现在他想在这些城市间修一些公路,当然并不是任意两个城市间都能修,为了道路系统的美观,一共只有 M 对城市间能修公路,即有若干三元组 (Ui, Vi,Ci) 表示 Ui 和 Vi 间有一条长度为 Ci 的双向道路。当然,游戏保证了,若所有道路都修建,那么任意两城市可以互相到达。

  Wayne 拥有恰好 N - 1 支修建队,每支队伍能且仅能修一条道路。当然,修建长度越大,修建的劳累度也越高,游戏设定是修建长度为 C 的公路就会有 C 的劳累度。当所有的队伍完工后,整个城市群必须连通,而这些修建队伍们会看看其他队伍的劳累情况,若劳累情况差异过大,可能就会引发骚动,不利于社会和谐发展。Wayne 对这个问题非常头疼,于是他想知道,这 N - 1 支队伍劳累度的标准差最小能有多少。

数据范围

  对于 $20\%$ 的数据,$M \leq 20$

  对于另外 $30\%$ 的数据,$C \leq 10$

  对于 $100\%$ 的数据,$N \leq 100$,$M \leq 2000$,$C \leq 100$

分析

  考场上写了个水法,后来发现似乎是正解喜闻乐见

  首先这是一道最小标准差生成树

  刚开始发现 $C$ 很小,感觉解法和这个有关,于是想到枚举平均数

  但是直接枚举出平均数是不存在的,考虑到标准差是个表示数据稳定性的量,所以可以在合理范围内枚举长度值,选取长度与之最接近的道路做生成树,然后算出真实平均值求标准差来更新答案

  由于所有道路的长度都是正整数,所以对于 $x \in (0.5k,0.5k+0.5) \; (k \in N)$,当 $k$ 取某固定值时,无论 $x$ 取何值,所有道路按长度与 $x$ 的差值从小到大排序的结果是相同的

  因此只需要每隔 $0.25$ 枚举一个长度值,当然也可以将所有道路长度都乘以 $4$

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 105
#define M 2005 inline int read() {
int x = , f = ; char ch = getchar();
while (ch < '' || ch > '') {if (ch == '-') f = -; ch = getchar();}
while (ch >= '' && ch <= '') {x = x * + ch - ''; ch = getchar();}
return x *= f;
} double ans = 1000000000.0;
int n, m, maxe, mine = inf;
int f[N], q[N]; struct Edge {int u, v, w, d;} e[M];
bool cmp(Edge a, Edge b) {return a.d < b.d;} int find(int x) {
if (x == f[x]) return x;
return f[x] = find(f[x]);
} int main() {
n = read(); m = read();
for (int i = ; i <= m; i++) {
e[i].u = read(); e[i].v = read(); e[i].w = read() * ;
maxe = max(maxe, e[i].w); mine = min(mine, e[i].w);
}
for (int k = mine; k <= maxe; k++) {
for (int i = ; i <= m; i++) e[i].d = abs(e[i].w - k);
sort(e + , e + m + , cmp);
int cnt = , sum = ; double now = ;
for (int i = ; i <= n; i++) f[i] = i;
for (int i = ; i <= m; i++) {
int x = find(e[i].u), y = find(e[i].v);
if (x == y) continue; f[x] = y;
q[++cnt] = i; sum += e[i].w / ;
if (cnt == n - ) break;
}
double avg = (double)sum / (double)(n - );
for (int i = ; i < n; i++)
now += (e[q[i]].w / 4.0 - avg) * (e[q[i]].w / 4.0 - avg);
now = sqrt(now / (n - ));
ans = min(ans, now);
}
printf("%.4lf", ans); return ;
}

T3 [JZOJ3682] Points and Segments

题目描述

  Lahub 在几何问题上准备得不充分,但是他听说这一年的 IOI 选拔夏令营中会出现许多几何问题。深陷恐惧的 Lahub 把他自己锁在了地下室里,并且开始思考这一类别的新题目。其中一个如下。
Lahub 想要在 OX 轴上画 n 条不同的线段 [li,ri]。线段可以是红色和蓝色其中任意一种。图画是“好”的当且仅当满足接下来的条件:

  对于每个 OX 轴上的点 x,考虑所有包含点 x 的线段,设有 rx 个红线段和 bx 个蓝线段包含点 x,必须满足不等式 |rx-bx|<=1。

  线段 [l,r] 包含点 x 当且仅当 l<= x<= r。

  Lahub 给你所有线段的左右端点,你不得不找到一个“好”的画法给他。

数据范围

  对于 $20\%$ 的数据,$N \leq 10$

  对于 $40\%$ 的数据,$N \leq 10^3$

  对于 $100\%$ 的数据,$N \leq 10^5$

分析

  根据差分的思想,一段区间被染色,就相当于 $l$ 加,$r+1$ 减

  首先当然要把点离散化,然后对于每个区间我们可以在 $l$ 和 $r+1$ 之间连一条无向边

  如果图中存在奇点(一定为偶数个),则可以从小到大组成若干对点,在每对点之间连一条虚边(任意两条虚边之间不存在重合部分),此时就形成了一个欧拉回路

  于是可以在图上跑一边欧拉回路,若经过某条边时方向向左,则对应区间被染成红色,反之则被染成蓝色,这样就能保证在每个点上红色和蓝色的覆盖次数之差的绝对值不超过 $1$

  因为这是个欧拉回路,覆盖每个点的红色区间和蓝色区间数量一定相等,且每个点最多被一条虚边覆盖,所以删去虚边后仍然符合题意

#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
using namespace std;
#define inf 0x3f3f3f3f
#define N 200005 inline int read() {
int x = , f = ; char ch = getchar();
while (ch < '' || ch > '') {if (ch == '-') f = -; ch = getchar();}
while (ch >= '' && ch <= '') {x = x * + ch - ''; ch = getchar();}
return x *= f;
} int n, m, tot = , last;
int to[N << ], num[N << ], nxt[N << ], head[N];
int q[N], d[N], vis[N], used[N << ], ans[N >> ];
struct Data {int l, r;} t[N >> ]; void add(int u, int v, int w) {
to[++tot] = v; num[tot] = w;
nxt[tot] = head[u]; head[u] = tot;
} void dfs(int x) {
vis[x] = ;
for (int &i = head[x]; i; i = nxt[i])
if (!used[i]) {
used[i] = used[i ^ ] = ;
ans[num[i]] = (to[i] > x);
dfs(to[i]);
}
} int main(){
n = read();
for (int i = ; i <= n; i++) {
t[i].l = read(); t[i].r = read() + ;
q[++m] = t[i].l; q[++m] = t[i].r;
}
sort(q + , q + m + );
m = unique(q + , q + m + ) - q - ;
for (int i = ; i <= n; i++) {
t[i].l = lower_bound(q + , q + m + , t[i].l) - q;
t[i].r = lower_bound(q + , q + m + , t[i].r) - q;
add(t[i].l, t[i].r, i); add(t[i].r, t[i].l, i);
d[t[i].l]++; d[t[i].r]++;
}
for (int i = ; i <= m; i++)
if (d[i] & ) {
if (last) {
add(last, i, ); add(i, last, );
d[last]++; d[i]++; last = ;
}
else last = i;
}
for (int i = ; i <= m; i++) if (!vis[i]) dfs(i);
for (int i = ; i <= n; i++) printf("%d ", ans[i]); return ;
}

2019-08-23 纪中NOIP模拟A组的更多相关文章

  1. 2019-08-21 纪中NOIP模拟A组

    T1 [JZOJ6315] 数字 题目描述

  2. 2019-08-09 纪中NOIP模拟B组

    T1 [JZOJ1035] 粉刷匠 题目描述 windy有N条木板需要被粉刷. 每条木板被分为M个格子. 每个格子要被刷成红色或蓝色. windy每次粉刷,只能选择一条木板上一段连续的格子,然后涂上一 ...

  3. 2019-08-15 纪中NOIP模拟B组

    T1 [JZOJ3455] 库特的向量 题目描述 从前在一个美好的校园里,有一只(棵)可爱的弯枝理树.她内敛而羞涩,一副弱气的样子让人一看就想好好疼爱她.仅仅在她身边,就有许多女孩子想和她BH,比如铃 ...

  4. 2019-08-12 纪中NOIP模拟B组

    T1 [JZOJ4879] 少女觉 题目描述 “在幽暗的地灵殿中,居住着一位少女,名为古明地觉.” “据说,从来没有人敢踏入过那座地灵殿,因为人们恐惧于觉一族拥有的能力——读心.” “掌控人心者,可控 ...

  5. 2019-08-01 纪中NOIP模拟B组

    T1 [JZOJ2642] 游戏 题目描述 Alice和Bob在玩一个游戏,游戏是在一个N*N的矩阵上进行的,每个格子上都有一个正整数.当轮到Alice/Bob时,他/她可以选择最后一列或最后一行,并 ...

  6. 2019-08-25 纪中NOIP模拟A组

    T1 [JZOJ6314] Balancing Inversions 题目描述 Bessie 和 Elsie 在一个长为 2N 的布尔数组 A 上玩游戏. Bessie 的分数为 A 的前一半的逆序对 ...

  7. 2019-08-20 纪中NOIP模拟B组

    T1 [JZOJ3490] 旅游(travel) 题目描述 ztxz16如愿成为码农之后,整天的生活除了写程序还是写程序,十分苦逼.终于有一天,他意识到自己的生活太过平淡,于是决定外出旅游丰富阅历. ...

  8. 2019-08-20 纪中NOIP模拟A组

    T1 [JZOJ6310] Global warming 题目描述 给定整数 n 和 x,以及一个大小为 n 的序列 a. 你可以选择一个区间 [l,r],然后令 a[i]+=d(l<=i< ...

  9. 2019-08-18 纪中NOIP模拟A组

    T1 [JZOJ6309] 完全背包 题目描述

随机推荐

  1. THINKPHP-RCE-POC

    thinkphp-RCE-POC 官方公告: 1.https://blog.thinkphp.cn/869075 2.https://blog.thinkphp.cn/910675 POC: thin ...

  2. Windows下CMD常用命令

    清理DNS的缓存 ipconfig /flushdns 查看dns nslookup 重置socket服务 netsh winsock reset 重置tcp/ip协议栈 netsh int ip r ...

  3. Properties(hashtable的子类)

    Properties: Properties是hashtable的子类(在java.util包中).该集合的特点:可以用于键值对形式的配置文件,且不允许Key重复,若有重复的,后者会覆盖前者. 也就是 ...

  4. get、post请求参数乱码解决方法(qq:1324981084)

    java高级架构师全套vip教学视频,需要的加我qq1324981084 在实际的项目中我们会遇见中文乱码的问题,这个问题是很恶心的事,所以我在这里提供了一些解决中文乱码的方法,希望能给大家一些帮助. ...

  5. 剖析Java OutOfMemoryError异常

    剖析Java OutOfMemoryError异常 在JVM中,除了程序计数器外,虚拟机内存中的其他几个运行时区域都有发生OutOfMemoryError异常的可能,本篇就来深入剖析一下各个区域出现O ...

  6. 字符串转数字 (With C++)

    1.stoi().stof().stod() 实现字符串转 int.float.double. stoi -> string to integer stof -> string to fl ...

  7. 方法中this指向的问题

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. css常用样式font控制字体的多种变换

    CSS 字体属性定义文本的字体系列.大小.加粗.风格(如斜体)和变形(如小型大写字母)font-family控制字体,由于各个电脑系统安装的字体不尽相同,但是基本装有黑体.宋体与微软雅黑这三款字体,通 ...

  9. docker jenkins 前端node项目 自动化部署异常 env: ‘node’: No such file or directory

    出现问题是docker jenkins 里面没有自动安装node导致找不到这个Node命令 解决方案:手动安装nodejs # 进入jenkins对应容器中 # docker exec -it [对应 ...

  10. JAVA系统架构高并发解决方案 分布式缓存 分布式事务解决方案

    JAVA系统架构高并发解决方案 分布式缓存 分布式事务解决方案