solved 7/11

2016 Multi-University Training Contest 10

题解链接

分类讨论 1001 Median(BH)

题意:

  有长度为n排好序的序列,给两段子序列[l1,r1],[l2,r2]构成新的序列,问中间的数字。

思路:

  根据不同情况分类讨论即可。时间复杂度O(1)。

代码:

#include <bits/stdc++.h>

const int N = 1e5 + 5;
int a[N];
int n, m;
int l1, r1, l2, r2;
int L1, L2, L;
int odd; double find3(int pos) {
int x = r2 - l2 + 1;
int d1 = l2 - l1;
int d2 = r1 - r2;
int id = 0;
double ret;
if (pos <= d1) {
id = l1 + pos - 1;
ret = a[id];
if (!odd) {
ret = (ret + a[id+1]) / 2.0;
}
}
else if (pos <= d1 + 2 * x) {
id = l2 + (pos - d1 - 1) / 2;
ret = a[id];
if (!odd) {
if ((pos-d1) % 2 == 0)
ret = (ret + a[id+1]) / 2.0;
}
}
else {
id = l1 + (pos - x) - 1;
ret = a[id];
if (!odd)
ret = (ret + a[id+1]) / 2.0;
}
return ret; } double find2(int pos) {
int x = r1 - l2 + 1;
int d1 = l2 - l1;
int d2 = r2 - r1;
int id = 0;
double ret;
if (pos <= d1) {
id = l1 + pos - 1;
ret = a[id];
if (!odd) {
ret = (ret + a[id+1]) / 2.0;
}
}
else if (pos <= d1 + 2 * x) {
id = l2 + (pos - d1 - 1) / 2;
ret = a[id];
if (!odd) {
if ((pos-d1) % 2 == 0)
ret = (ret + a[id+1]) / 2.0;
}
}
else {
id = l1 + (pos - x) - 1;
ret = a[id];
if (!odd)
ret = (ret + a[id+1]) / 2.0;
}
return ret;
} double find(int pos) {
int id = 0;
double ret;
if (pos <= L1) {
id = l1 + pos - 1;
ret = a[id];
if (!odd) {
if (id + 1 > r1)
ret = (ret + a[l2]) / 2.0;
else
ret = (ret + a[id+1]) / 2.0;
}
}
else {
id = l2 + (pos - L1) - 1;
ret = a[id];
if (!odd) {
ret = (ret + a[id+1]) / 2.0;
}
}
return ret;
} int main() {
int T;
scanf ("%d", &T);
while (T--) {
scanf ("%d%d", &n, &m);
for (int i=1; i<=n; ++i)
scanf ("%d", a+i);
while (m--) {
scanf ("%d%d%d%d", &l1, &r1, &l2, &r2);
if (l1 > l2) {
std::swap (l1, l2);
std::swap (r1, r2);
}
L1 = r1 - l1 + 1;
L2 = r2 - l2 + 1;
L = L1 + L2;
int mid = (L + 1) / 2;
odd = L & 1 ? 1 : 0; double ans = 0;
if (r1 < l2) {
ans = find (mid);
} else if (r1 <= r2) {
ans = find2 (mid);
} else {
ans = find3 (mid);
}
printf ("%.1f\n", ans);
}
}
return 0;
}

数学 1002 Hard problem(CYD)

递推(约瑟夫环变形) 1004 Death Sequence(BH)

题意:

  n个人排成一排,第一次:第1个人,第1+k个人,第1+2k个人。。。出队(枪毙);第二次剩下的人里第1个人,第1+k个人。。。出队。例子:1 2 3 4 5 6 7-> (1 3 5 7)(2 6)(4)。q次询问,每次问n个人出队后构成新的序列中第x个人。

思路:

  pair类型a[i]储存第i个数字是第几次出队的以及这个数字i。那么有递推式子:。前者的意思我想了想应该是i这个人在第x次第y个人出队,他和(i-(i-1)%k-1)这个人在第x-1次第y个人出队的命运类似,怎么推出来的呢,减去的是i前面有多少个在第1次出队的人数。然后只要sort一下,O(1)询问即可。

代码:

#include <bits/stdc++.h>

const int N = 3e6 + 5;
std::pair<int, int> a[N];
int ans[N]; int main() {
int T;
scanf ("%d", &T);
while (T--) {
int n, k, q;
scanf ("%d%d%d", &n, &k, &q);
for (int i=1; i<=n; ++i) {
if ((i-1) % k == 0)
a[i].first = 1;
else
a[i].first = a[i-(i-1)/k-1].first + 1;
a[i].second = i;
}
std::sort (a+1, a+1+n); while (q--) {
int id;
scanf ("%d", &id);
printf ("%d\n", a[id].second);
}
}
return 0;
}

线段树 1005 Road(BH)

代码:

#include <bits/stdc++.h>

typedef long long ll;
const int N = 2e5 + 5;
const int INF = 0x3f3f3f3f; int a[N];
int n, m; #define lch o << 1
#define rch o << 1 | 1 int mn[N<<2], mx[N<<2];
int sum[N<<2]; void push_down(int o) {
if (mn[o] != INF) {
mn[lch] = std::min (mn[lch], mn[o]);
mx[lch] = std::max (mx[lch], mx[o]);
mn[rch] = std::min (mn[rch], mn[o]);
mx[rch] = std::max (mx[rch], mx[o]);
}
} void build(int o, int l, int r) {
mn[o] = INF; mx[o] = 0;
sum[o] = 0;
if (l == r)
return ;
int mid = l + r >> 1;
build (lch, l, mid);
build (rch, mid+1, r);
} void modify(int o, int l, int r, int ql, int qr, int tim) {
if (ql <= l && r <= qr) {
mn[o] = std::min (mn[o], tim);
mx[o] = std::max (mx[o], tim);
return ;
}
push_down (o);
int mid = l + r >> 1;
if (ql <= mid)
modify (lch, l, mid, ql, qr, tim);
if (qr > mid)
modify (rch, mid+1, r, ql, qr, tim);
} void push_up(int o) {
sum[o] = sum[lch] + sum[rch];
} void modify2(int o, int l, int r, int pos, int v) {
if (l == r) {
sum[o] += v;
return ;
}
int mid = l + r >> 1;
if (pos <= mid)
modify2 (lch, l, mid, pos, v);
else
modify2 (rch, mid+1, r, pos, v);
push_up (o);
} struct Data {
int t, p, f;
bool operator < (const Data &rhs) const {
return t < rhs.t;
}
}data[N<<1];
int tot; void query(int o, int l, int r) {
if (l == r) {
if (mn[o] != INF) {
data[tot++] = {mn[o], l, 1};
data[tot++] = {mx[o]+1, l, -1};
}
return ;
}
push_down (o);
int mid = l + r >> 1;
query (lch, l, mid);
query (rch, mid+1, r);
} int l[N], r[N]; int main() {
while (scanf ("%d%d", &n, &m) == 2) {
n--;
for (int i=1; i<=n; ++i) {
scanf ("%d", &a[i]);
}
build (1, 1, n);
for (int i=1; i<=m; ++i) {
scanf ("%d%d", &l[i], &r[i]);
if (l[i] > r[i])
std::swap (l[i], r[i]);
r[i]--;
modify (1, 1, n, l[i], r[i], i);
}
tot = 0;
query (1, 1, n);
std::sort (data, data+tot);
int i = 0;
for (int day=1; day<=m; ++day) {
while (i<tot && data[i].t<=day) {
modify2 (1, 1, n, data[i].p, a[data[i].p]*data[i].f);
i++;
}
printf ("%d\n", sum[1]);
}
}
return 0;
}

  

线段树(线段涂色)1006 Counting Intersections(BH)

题意:

  有n条与坐标轴平行的线段,问横竖交叉点的个数。

思路:

  读完题目后能看出这题应该是数据结构题。如下图所示,也就是求所有蓝线和红线交点的个数。红线涂色,蓝线询问,按照x坐标排序,线段树询问y区间红线的当前x上条数。线段[x1,x2]都是可以相交的,我在x1的位置+1,代表插入这条线段,x2+1的位置-1,这条线段就没有了。时间复杂度O(nlogn)。

  这题思路+代码完成没有困难,可是比赛时出现两个失误:1. 数组开小了+数据结构使用不当(树状数组才过)T了好久;2. 数据范围估计出错了,原来要long long,1e5的数据,极限的测试数据:5e4的横线和5e4的竖线全部相交,5e4*5e4=25亿,超了int一点点。一定要注意这两个个问题。

代码:

#include <bits/stdc++.h>

const int N = 1e5 + 5;

struct Fenwick_Tree {
int C[N<<1], n;
void init(int n) {
memset (C, 0, sizeof (C));
this->n = n;
}
void modify(int i, int v) {
for (; i<=n; i+=i&(-i)) C[i] += v;
}
int query(int i) {
int ret = 0;
for (; i; i-=i&(-i)) ret += C[i];
return ret;
}
int query(int ql, int qr) {
return query (qr) - query (ql-1);
}
}bit; struct Point {
int x, y, c;
bool operator < (const Point &rhs) const {
return x < rhs.x;
}
}p[N<<1]; struct Query {
int x, y1, y2;
bool operator < (const Query &rhs) const {
return x < rhs.x;
}
}q[N]; int Y[N<<1];
int xm, ym;
int n, pm, qm; int get_y(int y) {
return std::lower_bound (Y, Y+ym, y) - Y + 1;
} long long solve() {
std::sort (Y, Y+ym);
ym = std::unique (Y, Y+ym) - Y;
std::sort (p, p+pm);
std::sort (q, q+qm); if (qm == 0 || pm == 0)
return 0; bit.init (ym); long long ret = 0;
int i = 0, j = 0;
int qx = q[0].x;
while (i < pm) {
int tx = p[i].x;
int ty = get_y (p[i].y);
if (tx <= qx) {
bit.modify (ty, p[i].c);
i++;
} else {
int qy1 = get_y (q[j].y1);
int qy2 = get_y (q[j].y2);
ret += bit.query (qy1, qy2);
j++;
if (j == qm)
break;
qx = q[j].x;
}
}
return ret;
} int main() {
int T;
scanf ("%d", &T);
while (T--) {
scanf ("%d", &n);
pm = qm = 0;
xm = ym = 0;
int x1, y1, x2, y2;
for (int i=0; i<n; ++i) {
scanf ("%d%d%d%d", &x1, &y1, &x2, &y2);
if (y1 == y2) {
if (x1 > x2)
std::swap (x1, x2);
p[pm++] = {x1, y1, 1};
p[pm++] = {x2+1, y2, -1};
Y[ym++] = y1;
} else {
if (y1 > y2)
std::swap (y1, y2);
q[qm++] = {x1, y1, y2};
Y[ym++] = y1; Y[ym++] = y2;
}
}
printf ("%I64d\n", solve ());
}
return 0;
}

DP+矩阵快速幂 1007 cjj's string game(BH)

代码:

#include <bits/stdc++.h>

typedef long long ll;
const int MOD = 1000000007;
const int N = 15; struct Matrix {
int row, col;
int arr[N][N];
Matrix(int r=0, int c=0) {
row = r; col = c;
memset (arr, 0, sizeof (arr));
}
Matrix operator * (const Matrix &B) {
Matrix ret(row, B.col);
for (int i=0; i<row; ++i) {
for (int j=0; j<B.col; ++j) {
for (int k=0; k<col; ++k) {
ret.arr[i][j] = (ret.arr[i][j] + (ll) arr[i][k] * B.arr[k][j]) % MOD;
}
}
}
return ret;
}
void unit(int n) {
row = col = n;
for (int i=0; i<n; ++i) {
arr[i][i] = 1;
}
}
};
Matrix operator ^ (Matrix X, int n) {
Matrix ret; ret.unit (X.col);
while (n) {
if (n & 1) {
ret = ret * X;
}
X = X * X;
n >>= 1;
}
return ret;
} int main() {
int T;
scanf ("%d", &T);
while (T--) {
int n, m, k;
scanf ("%d%d%d", &n, &m, &k);
Matrix x (m+1, m+1);
for (int i=0; i<=m; ++i) {
x.arr[i][0] = k * k - k;
if (i < m)
x.arr[i][i+1] = k;
}
x = x ^ n; int ans = 0;
for (int i=0; i<=m; ++i) {
ans = (ans + x.arr[0][i]) % MOD;
} Matrix y (m, m);
for (int i=0; i<m; ++i) {
y.arr[i][0] = k * k - k;
if (i < m - 1)
y.arr[i][i+1] = k;
}
y = y ^ n;
for (int i=0; i<m; ++i) {
ans = (ans - y.arr[0][i] + MOD) % MOD;
} printf ("%d\n", ans);
}
return 0;
}

  

模拟 1011 Water problem(CYD)

2016 Multi-University Training Contest 10的更多相关文章

  1. 2016 Al-Baath University Training Camp Contest-1

    2016 Al-Baath University Training Camp Contest-1 A题:http://codeforces.com/gym/101028/problem/A 题意:比赛 ...

  2. hdu 5416 CRB and Tree(2015 Multi-University Training Contest 10)

    CRB and Tree                                                             Time Limit: 8000/4000 MS (J ...

  3. 2015 Multi-University Training Contest 10 hdu 5406 CRB and Apple

    CRB and Apple Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)To ...

  4. 2015 Multi-University Training Contest 10 hdu 5412 CRB and Queries

    CRB and Queries Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Other ...

  5. [二分,multiset] 2019 Multi-University Training Contest 10 Welcome Party

    Welcome Party Time Limit: 4000/4000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)T ...

  6. 2015 Multi-University Training Contest 10(9/11)

    2015 Multi-University Training Contest 10 5406 CRB and Apple 1.排序之后费用流 spfa用stack才能过 //#pragma GCC o ...

  7. 2016 Multi-University Training Contest 10 || hdu 5860 Death Sequence(递推+单线约瑟夫问题)

    题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=5860 题目大意:给你n个人排成一列编号,每次杀第一个人第i×k+1个人一直杀到没的杀.然后 ...

  8. 2016 Multi-University Training Contest 10 [HDU 5861] Road (线段树:区间覆盖+单点最大小)

    HDU 5861 题意 在n个村庄之间存在n-1段路,令某段路开放一天需要交纳wi的费用,但是每段路只能开放一次,一旦关闭将不再开放.现在给你接下来m天内的计划,在第i天,需要对村庄ai到村庄bi的道 ...

  9. 2016 Multi-University Training Contest 10 solutions BY BUPT

    1001. 一个数组上的两个区间求中位数,可以通过分类讨论直接找到中位数,复杂度O(1).不过本题数据较小,优美的log(n)也可过. 1002. 直接求得阴影面积表达式即可. 1003. 二分完成时 ...

随机推荐

  1. 域名在微信朋友圈内分享需要ICP备案 杜绝不良信息传播

    就在刚刚,腾讯微信团队发布公告表示域名在朋友圈内分享需要ICP备案,杜绝打击不良互联网信息的传播.公告称根据互联网管理相关规定,即日起在微信朋友圈内分享的域名,请在2014年12月31日前完成ICP备 ...

  2. CocoStudio基础教程(1)创建UI并载入到程序中

    1.概述 CocoStudio的使用无疑是cocos2d-x 3.0的重要组成部分,接下来我们用它来创建一组UI,并将其读入到程序中显示出来.先上效果图: 2.导出 在导出之前,最好先创建一个新的工程 ...

  3. Linux下建立软链接

    实例:ln -s /home/gamestat    /gamestat Linux下的软链接类似于windows下的快捷方式 ln -s a b 中的 a 就是源文件,b是链接文件名,其作用是当进入 ...

  4. shell截取字符串

    image_tag="pangu-20151021102145\"" 1.用#号截取,符号-右面所有字符串 TMP=${image_tag#*-} echo $TMP 得 ...

  5. ThinkPHP 分页实现

    TP3.2框架手册,有一个数据分页,不过每次都要写太多的代码,还有中文设置等有些麻烦,做为程序开发者,有必要整理下: O.先看效果图 一.分页方法 /** * TODO 基础分页的相同代码封装,使前台 ...

  6. js 判断所有节假日

    // JavaScript Document calendar = new Date(); month = calendar.getMonth(); date = calendar.getDate() ...

  7. CVPR2015文章下载

    http://www.cv-foundation.org/openaccess/content_cvpr_2015/html/Liu_Real-Time_Part-Based_Visual_2015_ ...

  8. python 中接口的实现

    实际上,由于python是动态语言,支持多继承,因此接口在语言层面,是没有的东东. 然后,在架构设计上,我们又需要这么一个东西,来规范开发人员的行为. 因此就有了zope.interface的诞生. ...

  9. python 的编码问题

    老是碰到这个问题,决定好好给整理一番思路. 翻阅资料和实践证明,以下论述为真理: 字符串在Python内部的表示是unicode编码,因此,在做编码转换时,通常需要以unicode作为中间编码,即先将 ...

  10. users

    NAME users - print the user names of users currently logged in to the current host SYNOPSIS users [O ...