开学第五测
开学第五测
T1 期望得分:100;实际得分:70
锻炼计划(exercise.pas)
身体是革命的本钱,OIers不要因为紧张的学习和整天在电脑前而忽视了健康问题。小x设计了自己的锻炼计划,但他不知道这个计划是否可行,换句话说如果计划不当可能会让他的体力超支,所以小x请你帮助他。
一天有1440分钟,所以小x列出的是这一整天第1至第1440分钟的计划。小x的体力用一个整数来表示,他会按照计划表进行锻炼,同时,每分钟小x的体力会自动增加1。如果某一分钟末小x的体力小于等于零,那么可怜的小x就累死了……
输入(exercise.in)
第一行是用空格分开的两个整数n,m,分别表示小x的初始体力值和计划的项目数量。
从第二行开始的m行,每行描述一个锻炼项目:名称、开始时间a、结束时间b、每分钟耗费的体力(用空格分隔),表示此项目从第a分钟初开始,第b分钟末结束。锻炼项目按照开始时间递增顺序给出,不会出现两个项目时间冲突的情况。
输出(exercise.out)
输出包括两行,如果计划可行,第一行输出"Accepted",第二行输出这一天过后最后剩余的体力;否则在第一行输出"Runtime Error",第二行输出在第几分钟累死。
样例
Input |
Output |
10 1 Basketball 1 10 1 |
Accepted 1440 |
1 1 Nunchakus 1 1 2 |
Runtime Error 1 |
数据范围
0<n<=2^31-1
0<=m<=500
所有中间值的绝对值不会超过2^31-1
每一个锻炼项目的名称不超过20个字符,其中不含空格。
思路:简单的模拟(不知道为什么WA掉两个点 qwq)
#include<algorithm> #include<iostream> #include<cstring> #include<cstdio> using namespace std; int n, m, sum, ans; int l[505], r[505], t[505]; string s; int main() { //freopen("exercise.in","r",stdin); //freopen("exercise.out","w",stdout); scanf("%d%d", &n, &m); ans = n; sum = 1440; for(int i = 1; i <= m; i++) { cin >> s >> l[i] >> r[i] >> t[i]; sum -= r[i]-l[i]+1; } for(int i = 1; i <= m; i++) for(int j = l[i]; j <= r[i]; j++) { ans = ans-t[i]+1; if(ans <= 0) { printf("Runtime Error\n%d", j); return 0; } } printf("Accepted\n%d", ans+sum); //fclose(stdin); fclose(stdout); return 0; }
#include<algorithm> #include<iostream> #include<cstring> #include<cstdio> #include<cmath> #define maxn 510 #define ll long long using namespace std; ll now, n, falg; struct node{ ll a, b, c; }p[maxn]; ll init() { //读入优化 ll x = 0, f = 1; char s = getchar(); while(s<'0' || s>'9'){ if(s == '-') f = -1; s = getchar(); } while(s>='0' && s<='9'){ x = x*10+s-'0'; s = getchar(); } return x * f; } ll Cal(ll x, ll y) { if(x%y == 0) return x/y; else return x/y+1; } int main() { //freopen("exercise.in","r",stdin); //freopen("exercise.out","w",stdout); now = init(); n = init(); for(int i = 1; i <= n; i++) { p[i].a = init(); p[i].b = init(); p[i].c = init(); } for(int i = 1; i <= n; i++) { now += p[i].a-p[i-1].b-1; if(now-(p[i].b-p[i].a+1)*p[i].c+p[i].b-p[i].a+1 > 0) now = now-(p[i].b-p[i].a+1)*p[i].c+p[i].b-p[i].a+1; else { now = Cal(now+p[i].a*p[i].c-p[i].a-p[i].c+1, p[i].c-1); falg =1 ; break; } } if(falg) cout << "Runtime Error" << endl << now << endl; else cout << "Accepted" << endl << now+1440-p[n].b << endl; return 0; }
T2 期望得分:40;实际得分:40
魔兽争霸(war.pas)
小x正在销魂地玩魔兽
他正控制着死亡骑士和n个食尸鬼(编号1~n)去打猎
死亡骑士有个魔法,叫做“死亡缠绕”,可以给食尸鬼补充HP
战斗过程中敌人会对食尸鬼实施攻击,食尸鬼的HP会减少
小x希望随时知道自己部队的情况,即HP值第k多的食尸鬼有多少HP,以便决定如何施放魔法
请同学们帮助他:)
小x向你发出3种信号:(下划线在输入数据中表现为空格)
A_i_a表示敌军向第i个食尸鬼发出了攻击,并使第i个食尸鬼损失了a点HP,如果它的HP<=0,那么这个食尸鬼就死了(Undead也是要死的……)。
敌军不会攻击一个已死的食尸鬼。
C_i_a 表示死亡骑士向第i个食尸鬼放出了死亡缠绕,并使其增加了a点HP。
HP值没有上限。
死亡骑士不会向一个已死的食尸鬼发出死亡缠绕
Q_k 表示小x向你发出询问
输入(war.in)
第一行,一个正整数 n
以后n个整数 表示n个食尸鬼的初始HP值
接着一个正整数m
以下m行 每行一个小x发出的信号
输出(war.out)
对于小x的每个询问,输出HP第k多的食尸鬼有多少HP,如果食尸鬼总数不足k个,输出-1。每个一行数。
最后一行输出一个数:战斗结束后剩余的食尸鬼数
样例
Input | Output |
5 1 2 3 4 5 10 Q 2 A 4 6 C 1 4 Q 2 A 2 1 A 3 3 A 1 3 Q 4 C 2 10 Q 1 |
4 5 -1 11 3 |
约定
40%的数据 n<=3000 m<=5000
70%的数据 n<=8000 m<=10000
100%的数据 n<=30000 m<=50000
90%的数据随机生成
食尸鬼HP没有上限
数据保证任意时刻食尸鬼的HP值在longint范围内
数据保证A和C命令中的食尸鬼是活着的
输入数据中没有多余空格、换行
思路:平衡树/伸展树(splay)
某同学用Trie树A了,然而我不会,用线段树 T 了 6 个点
#include<algorithm> #include<iostream> #include<cstring> #include<cstdio> #define N 30005 #define LL long long using namespace std; int n, m, x, y, tot, tat; LL a[N]; char ch; struct nond { int ll, rr; LL hp; }tree[4*N]; bool cmp(LL x, LL y) { return x > y; } void build(int now, int l, int r) { tree[now].ll = l; tree[now].rr = r; if(l == r) { scanf("%lld", &tree[now].hp); a[++tot] = tree[now].hp; return ; } int mid = (l+r) / 2; build(now*2, l, mid); build(now*2+1, mid+1, r); } void change(int now, int x, LL y) { //被攻击 if(tree[now].ll == tree[now].rr) { for(int i = 1; i <= tot; i++) if(a[i] == tree[now].hp) { a[i] -= y; break; } tree[now].hp -= y; if(tree[now].hp <= 0) tat--; return ; } int mid = (tree[now].ll+tree[now].rr) / 2; if(x<=mid) change(now*2, x, y); else change(now*2+1, x, y); } void add(int now, int x, LL y) { //“死亡缠绕”回血 if(tree[now].ll == tree[now].rr) { for(int i = 1; i <= tot; i++) if(a[i] == tree[now].hp) { a[i] += y; break; } tree[now].hp += y; return ; } int mid = (tree[now].ll+tree[now].rr) / 2; if(x<=mid) add(now*2, x, y); else add(now*2+1, x, y); } LL find(int k) { //查询第k大的HP值 if(tat < k) return -1; sort(a+1, a+tot+1, cmp); return a[k]; } int main() { //freopen("war.in","r",stdin); //freopen("war.out","w",stdout); scanf("%d", &n); build(1, 1, n); tat = n; scanf("%d", &m); for(int i = 1; i <= m; i++) { cin >> ch; if(ch == 'A') { scanf("%d%d", &x, &y); change(1, x, y); } if(ch == 'C') { scanf("%d%d", &x, &y); add(1, x, y); } if(ch == 'Q') { scanf("%d", &x); printf("%lld\n", find(x)); } } printf("%lld", tat); //最后剩余的食尸鬼数量 //fclose(stdin); fclose(stdout); return 0; }
#include<algorithm> #include<iostream> #include<cstring> #include<cstdio> #define maxn 100010 #define lc k*2 #define rc k*2+1 #define mid (l+r)/2 using namespace std; int n, m, num; int a[maxn], b[maxn], c[maxn], s[maxn*4]; struct node { int x, y; char z; }p[maxn]; int init() { int x = 0, f = 1; char s = getchar(); while(s<'0' || s>'9') { if(s == '-') f = -1; s = getchar(); } while(s>='0' && s<='9') { x = x*10+s-'0'; s = getchar(); } return x * f; } void Insert(int k, int l, int r, int x, int y) { if(l==x && r==x) { s[k] += y; return; } if(x <= mid) Insert(lc, l, mid, x, y); else Insert(rc, mid+1, r, x, y); s[k] = s[lc]+s[rc]; } int Query(int k, int l, int r, int x){ if(l == r) return l; if(x > s[lc]) return Query(rc, mid+1, r, x-s[lc]); else return Query(lc, l, mid, x); } int main() { // freopen("war.in","r",stdin); // freopen("war.out","w",stdout); n = init(); for(int i = 1; i <= n; i++) { a[i] = init(); b[i] = a[i]; c[++num] = a[i]; } m = init(); for(int i = 1; i <= m; i++) { cin >> p[i].z; p[i].x = init(); if(p[i].z != 'Q') p[i].y = init(); if(p[i].z == 'A') { b[p[i].x] -= p[i].y; if(b[p[i].x] > 0) c[++num] = b[p[i].x]; } if(p[i].z=='C' && b[p[i].x]>0) { b[p[i].x] += p[i].y; c[++num] = b[p[i].x]; } } sort(c+1, c+1+num); int pos, X, Y; num = unique(c+1, c+1+num)-c-1; for(int i = 1; i <= n;i++) { pos = lower_bound(c+1, c+1+num, a[i])-c; Insert(1, 1, num, pos, 1); } for(int i = 1; i <= m; i++) { if(p[i].z == 'Q') { if(s[1] < p[i].x) { printf("-1\n"); continue; } pos = Query(1, 1, num, s[1]-p[i].x+1); printf("%d\n", c[pos]); } if(p[i].z == 'A') { X = a[p[i].x]; a[p[i].x] -= p[i].y; pos = lower_bound(c+1, c+1+num, X)-c; Insert(1, 1, num, pos, -1); Y = a[p[i].x]; if(Y <= 0) continue; pos = lower_bound(c+1, c+1+num, Y)-c; Insert(1, 1, num, pos, 1); } if(p[i].z == 'C') { X = a[p[i].x]; if(X <= 0) continue; a[p[i].x] += p[i].y; pos = lower_bound(c+1, c+1+num, X)-c; Insert(1, 1, num, pos, -1); Y = a[p[i].x]; pos = lower_bound(c+1, c+1+num, Y)-c; Insert(1, 1, num, pos, 1); } } printf("%d\n", s[1]); return 0; }
T3 期望得分 = 实际得分 = 0 (此题已暂时弃疗)
暗黑破坏神(diablo.pas)
无聊中的小x玩起了Diablo I...
游戏的主人公有n个魔法
每个魔法分为若干个等级,第i个魔法有p[i]个等级(不包括0)
每个魔法的每个等级都有一个效果值,一个j级的i种魔法的效果值为w[i][j]
魔法升一级需要一本相应的魔法书
购买魔法书需要金币,第i个魔法的魔法书价格为c[i]
而小x只有m个金币(好孩子不用修改器)
你的任务就是帮助小x决定如何购买魔法书才能使所有魔法的效果值之和最大
开始时所有魔法为0级 效果值为0
输入(diablo.in)
第一行 用空格隔开的两个整数n m
以下n行 描述n个魔法
第i+1行描述 第i个魔法 格式如下
c[i] p[i] w[i][1] w[i][2] ... w[i][p[i]]
输出(diablo.out)
第一行输出一个整数,即最大效果值。
以后n行输出你的方案:
第i+1行有一个整数v[i] 表示你决定把第i个魔法学到v[i]级
如果有多解 输出花费金币最少的一组
如果还多解 输出任意一组
样例
Input |
Output |
3 10 1 3 1 2 2 2 3 2 4 6 3 3 2 1 10 |
11 1 0 3 |
约定
0<n<=100
0<m<=500
0<p[i]<=50
0<c[i]<=10
保证输入数据和最终结果在longint范围内
思路:自我感觉是背包,but 标程用的DFS hua ji
#include<iostream> #include<cstring> #include<cstdio> #define maxn 510 using namespace std; int n, m, ans, C, r[20]; int c[maxn], p[maxn], w[maxn][maxn]; int init() { int x = 0, f = 1; char s = getchar(); while(s<'0' || s>'9') { if(s == '-') f = -1; s = getchar(); } while(s>='0' && s<='9') { x = x*10+s-'0'; s = getchar(); } return x * f; } void Dfs(int s, int x[], int v) { if(s > m) return; if(v > ans) memcpy(r, x, sizeof(r)), ans = v; else if(v==ans && s<C) memcpy(r, x, sizeof(r)), C = s; for(int i = 1; i <= n; i++) if(x[i] < p[i]) { x[i]++; int now = 0; for(int j = 1; j <= n; j++) now += w[j][x[j]]; Dfs(s+c[i], x, now); x[i]--; } } int main() { // freopen("diablo.in","r",stdin); // freopen("diablo.out","w",stdout); n = init(); m = init(); for(int i = 1; i <= n; i++) { c[i] = init(); p[i] = init(); for(int j = 1; j <= p[i]; j++) w[i][j] = init(); } int x[20] = {0}; Dfs(0, x, 0); printf("%d\n", ans); for(int i = 1; i <= n; i++) printf("%d\n", r[i]); return 0; }