机房水题欢乐赛 2016-02-17

来源:互联网 发布:java删除文件 编辑:程序博客网 时间:2024/04/30 04:56

考试时题面用pdf格式给却不是latex生成的,严重吐槽
今天bzoj好像出事了。。

T1: 数字

给你N个数,编号1~N,从某个区间[L,R]中,任意选择二个数字,它们相同的概率是多少。

Input

第一行一个整数N
接下来一行,N个整数。
第三行一个整数M,表示询问次数。
接下来M行,每行两个整数L,R

Output

M行,每行一个分数,表示两个数字是相同的概率,必须为最简分数。

Sample Input

6 41 2 3 3 3 22 61 33 51 6

Sample Output

2/5
0/1
1/1
4/15

Hint

40%:n,m500
60%:n,m5000
100%:n,m50000

Solution

实际上是 BZOJ 2038…
http://www.lydsy.com/JudgeOnline/problem.php?id=2038
到时再新开帖子贴题解吧。。
另外吐槽欢乐赛出题人(好像哪里不对),强行改样例不改数据。好懒(好像就在说我)
而且数据很水O(n2)的暴力竟然90分。。
好像数据没判断0/1和0/0。
暂时贴个暴力。。

#include <cstdio>#include <cstring>#include <algorithm>using namespace std;#define FOR(i,j,k) for(i=j;i<=k;i++)#define rep(i,j,k) for(i=j;i<k;i++)typedef long long ll;ll read() {    ll s = 0, f = 1; char ch = getchar();    for (; ch < '0' || ch > '9'; ch = getchar()) if (ch == '-') f = -1;    for (; '0' <= ch && ch <= '9'; ch = getchar()) s = s * 10 + ch - '0';    return s * f;}const int N = 50105;ll a[N], b[N], c[N];ll gcd(ll a, ll b) {    if (!b) return a;    else return gcd(b, a % b);}int main() {    ll n, m, i, j, x, y;    n = read();    FOR(i,1,n) a[i] = b[i] = read();    sort(b + 1, b + n + 1);    FOR(i,1,n) a[i] = lower_bound(b + 1, b + n + 1, a[i]) - b;    m = read();    FOR(i,1,m) {        x = read(), y = read();        ll ans2 = 0, ans1 = 0;        memset(c, 0, sizeof c);        FOR(j,x,y) ans1 += j - x - c[a[j]], ++c[a[j]], ans2 += j - x;        ans1 = ans2 - ans1;        ll g = gcd(ans1, ans2);        if (g == 0) g = 1;        printf("%I64d/%I64d\n", ans1 / g, ans2 / g);    }    return 0;}

T2:栅栏

http://blog.csdn.net/huanghongxun/article/details/50646716

T3:伸缩门

有一个专门接待嘉宾的餐厅,它的营业时间是[0,T]时刻。餐厅有一个神奇的伸缩门,门的高度可以在[0,K]之间变动,而且在每个单位时间,门可以变大一个单位,也可以缩小一个单位,当然也可以不变(变动的范围不能超过边界)。

在刚开始的时候,这个门的高度为 0,意味着门是关着的。现在有 n 个贵宾要通过这扇门。每个嘉宾的身高 si 和重要度 pi,以及到达的时间 ti 是不一样的。嘉宾将在 ti 时间到达门前,如果此时门的高度刚好等于嘉宾的身高 si 时,嘉宾才会认为这扇门是专门为他而开的,所以他才会进入餐厅。

问,怎么安排伸缩门,才能使进入餐厅的嘉宾的重要度和最大。

Input

第一行三个整数, N, K, T
接下来 3 行。
第一行是t1,t2,,tn,表示 1~N 嘉宾到达的时间
第二行是p1,p2,,pn,表示嘉宾的重要度
第三行是s1,s2,,sn,表示嘉宾的身高。

Output

一行一个整数,表示进入餐厅的嘉宾的最大重要度之和。

Sample Input

4 10 20
10 16 8 16
10 11 15 1
10 7 1 8

Sample Output

26

Hint

1n,k100
0t30000
0tit
0pi300
1sik

Solution

一个简单的dp。
先按时间排序嘉宾。
fi,j表示轮到第i个嘉宾的时候,当前门的高度是j的最大重要度和。
那么显然有

fi,j=max{fi1,c+q}(c[0,min{k,titi1}],q=(ifj=si)?pi:0)

#include <cstdio>#include <cstring>#include <algorithm>using namespace std;#define FOR(i,j,k) for(i=j;i<=k;i++)#define rep(i,j,k) for(i=j;i<k;i++)inline int read() {    int s = 0, f = 1; char ch = getchar();    for (; ch < '0' || ch > '9'; ch = getchar()) if (ch == '-') f = -1;    for (; '0' <= ch && ch <= '9'; ch = getchar()) s = s * 10 + ch - '0';    return s * f;}inline void getmax(int &a, int b) { if (a < b) a = b; }const int N = 128, inf = 0x7f7f7f7f;struct Person {    int t, p, s;    bool operator< (const Person &b) const {        return t < b.t;    }} p[N];int f[N][N];int main() {    int n = read(), k = read(), t = read(), i, j, c, q, ans = 0;    FOR(i,1,n) p[i].t = read();    FOR(i,1,n) p[i].p = read();    FOR(i,1,n) p[i].s = read();    sort(p + 1, p + n + 1);    FOR(i,1,n) if (p[i].t > t) n = i - 1;    FOR(i,1,k) f[0][i] = -inf;    f[0][0] = 0;    FOR(i,1,n) FOR(j,1,k) {        q = j == p[i].s ? p[i].p : 0;        f[i][j] = -inf;        FOR(c,0,min(k,p[i].t-p[i-1].t)) {            if (j+c<=k) getmax(f[i][j], f[i-1][j+c] + q);            if (j-c>=0) getmax(f[i][j], f[i-1][j-c] + q);        }    }    FOR(j,1,k) getmax(ans, f[n][j]);    printf("%d", ans);    return 0;}

T4: 逆序数

给定一个正整数序列,总共有 N 个数。问逆序数是多少?逆序数为逆序对的个数。逆序对的定义:假如一个正整数序列为 1,3,4,2,5.则逆序数为 2.
因为 3, 2 构成一个逆序对, 4, 2 构成一个逆序对。当排在前面的数字大于后面的某个数字时,则这两个数字构成一个逆序对。

Input

第一行一个正整数 N
接下来 N 个正整数,表示这个正整数序列。

Output

一行一个正整数,表示逆序数。

Sample Input

61 3 2 6 5 4

Sample Output

4

Sample Explanation

样例:(3,2),(6,5),(6,4),(5,4)。

Hint

50%:n1000
100%:n100000

Solution

逆序对裸题(输入法好坑啊)。。。。。。。
我选择树状数组233。

#include <cstdio>#include <cstring>#include <algorithm>using namespace std;#define FOR(i,j,k) for(i=j;i<=k;i++)#define rep(i,j,k) for(i=j;i<k;i++)typedef long long ll;ll read() {    ll s = 0, f = 1; char ch = getchar();    for (; ch < '0' || ch > '9'; ch = getchar()) if (ch == '-') f = -1;    for (; '0' <= ch && ch <= '9'; ch = getchar()) s = s * 10 + ch - '0';    return s * f;}const int N = 100100;ll a[N], b[N], c[N], n;void add(ll i, ll x) {    for (; i <= n; i += i & -i) c[i] += x;}ll sum(ll i) {    ll s = 0;    for (; i; i -= i & -i) s += c[i];    return s;}int main() {    ll i, ans = 0;    n = read();    FOR(i,1,n) a[i] = b[i] = read();    sort(b + 1, b + n + 1);    FOR(i,1,n) a[i] = lower_bound(b + 1, b + n + 1, a[i]) - b;    FOR(i,1,n) {        ans += sum(n) - sum(a[i]);        add(a[i], 1);    }    printf("%I64d", ans);    return 0;}

总结

没能AK真是可惜。
莫队忘了还得复习(腹泻)。

0 0
原创粉丝点击