历年NOIP水题泛做
快noip了就乱做一下历年的noip题目咯..
noip2014 飞扬的小鸟
其实这道题并不是很难,但是就有点难搞 听说男神错了一个小时..
就是$f_{i,j}$表示在第$i$个位置高度为$j$的时候最小点击次数
递推的话对于上升的情况只做一次,后面几次在后面再做..
- #include <cstdio>
- #include <cstring>
- #include <cstdlib>
- #include <algorithm>
- using namespace std;
- const int Maxn = 10010;
- const int Maxm = 1010;
- const int inf = 1e9;
- int f[2][Maxm];
- int n, m, K;
- int l[Maxn], u[Maxn]; bool p[Maxn];
- int X[Maxn], Y[Maxn];
- int _min ( int x, int y ){ return x < y ? x : y; }
- int main (){
- int i, j, k;
- scanf ( "%d%d%d", &n, &m, &K );
- l[0] = 0; u[0] = m+1;
- for ( i = 1; i <= n; i ++ ){ scanf ( "%d%d", &X[i], &Y[i] ); l[i] = 0; u[i] = m+1; }
- for ( i = 1; i <= K; i ++ ){
- int x;
- scanf ( "%d", &x );
- p[x] = true;
- scanf ( "%d%d", &l[x], &u[x] );
- }
- int st = 0;
- for ( i = 0; i <= m; i ++ ) f[st][i] = 0;
- int num = 0;
- for ( i = 1; i <= n; i ++ ){
- st = st^1;
- for ( j = 0; j <= m; j ++ ) f[st][j] = inf;
- bool bk = false;
- for ( j = l[i-1]+1; j < u[i-1]; j ++ ){
- if ( f[st^1][j] == inf ) continue;
- bk = true;
- f[st][_min(j+X[i],m)] = _min ( f[st][_min(j+X[i],m)], f[st^1][j]+1 );
- }
- for ( j = 0; j <= m; j ++ ){
- if ( f[st][j] != inf ) f[st][_min(j+X[i],m)] = _min ( f[st][_min(j+X[i],m)], f[st][j]+1 );
- }
- for ( j = l[i-1]+1; j < u[i-1]; j ++ ){
- if ( f[st^1][j] == inf ) continue;
- if ( j-Y[i] > l[i] && j-Y[i] < u[i] ) f[st][j-Y[i]] = _min ( f[st][j-Y[i]], f[st^1][j] );
- }
- if ( bk == false ){ printf ( "0\n%d\n", num-1 ); return 0; }
- if ( p[i] == true ) num ++;
- }
- int ans = inf;
- for ( i = 1; i <= m; i ++ ) ans = _min ( ans, f[st][i] );
- printf ( "1\n%d\n", ans );
- return 0;
- }
noip2013 货车运输
就是裸的最大瓶颈树..
通俗点说就是最大生成树再用st表维护一下路径最小值..
- #include <cstdio>
- #include <cstring>
- #include <cstdlib>
- #include <algorithm>
- using namespace std;
- const int Maxn = 10010;
- const int Maxm = 50010;
- struct node {
- int y, next, d;
- }a[Maxn*2]; int first[Maxn], len;
- void ins ( int x, int y, int d ){
- len ++;
- a[len].y = y; a[len].d = d;
- a[len].next = first[x]; first[x] = len;
- }
- struct lnode {
- int x, y, d;
- }list[Maxm];
- bool cmp ( lnode x, lnode y ){ return x.d > y.d; }
- int n, m, q;
- int fa[Maxn]; bool fw[Maxn];
- int ff ( int x ){
- if ( fa[x] == x ) return x;
- return fa[x] = ff (fa[x]);
- }
- int minn[Maxn][15], fat[Maxn][15], dep[Maxn];
- int _min ( int x, int y ){ return x < y ? x : y; }
- void dfs ( int x, int f ){
- fw[x] = true;
- for ( int i = 1; i <= 14; i ++ ){
- fat[x][i] = fat[fat[x][i-1]][i-1];
- minn[x][i] = _min ( minn[x][i-1], minn[fat[x][i-1]][i-1] );
- }
- for ( int k = first[x]; k; k = a[k].next ){
- int y = a[k].y;
- if ( y == f ) continue;
- fat[y][0] = x;
- minn[y][0] = a[k].d;
- dep[y] = dep[x]+1;
- dfs ( y, x );
- }
- }
- int lca ( int x, int y ){
- int ret = 0x7fffffff;
- if ( dep[x] < dep[y] ) swap ( x, y );
- for ( int i = 14; i >= 0; i -- ){
- if ( dep[fat[x][i]] >= dep[y] ){
- ret = _min ( ret, minn[x][i] );
- x = fat[x][i];
- }
- }
- if ( x == y ) return ret;
- for ( int i = 14; i >= 0; i -- ){
- if ( fat[x][i] != fat[y][i] ){
- ret = _min ( ret, minn[x][i] );
- ret = _min ( ret, minn[y][i] );
- x = fat[x][i]; y = fat[y][i];
- }
- }
- return _min ( ret, _min ( minn[x][0], minn[y][0] ) );
- }
- int main (){
- int i, j, k;
- scanf ( "%d%d", &n, &m );
- for ( i = 1; i <= m; i ++ ){
- scanf ( "%d%d%d", &list[i].x, &list[i].y, &list[i].d );
- }
- sort ( list+1, list+m+1, cmp );
- for ( i = 1; i <= n; i ++ ) fa[i] = i;
- for ( i = 1; i <= m; i ++ ){
- int fx = ff (list[i].x), fy = ff (list[i].y);
- if ( fx != fy ){
- fa[fy] = fx;
- ins ( list[i].x, list[i].y, list[i].d );
- ins ( list[i].y, list[i].x, list[i].d );
- }
- }
- for ( i = 1; i <= n; i ++ ){
- if ( fw[i] == false ){ dep[i] = 1; dfs ( i, 0 ); }
- }
- scanf ( "%d", &q );
- for ( i = 1; i <= q; i ++ ){
- int x, y;
- scanf ( "%d%d", &x, &y );
- int fx = ff (x), fy = ff (y);
- if ( fx != fy ) printf ( "-1\n" );
- else printf ( "%d\n", lca ( x, y ) );
- }
- return 0;
- }
noip2015 跳石头
二分答案,然后找第一个距离超过这个答案的使用,扫一遍即可
- #include <cstdio>
- #include <cstring>
- #include <cstdlib>
- #include <algorithm>
- using namespace std;
- const int Maxn = 50010;
- int a[Maxn], n, m, L;
- int main (){
- int i, j, k;
- scanf ( "%d%d%d", &L, &n, &m );
- for ( i = 1; i <= n; i ++ ) scanf ( "%d", &a[i] );
- a[++n] = L;
- int l = 1, r = L, ret;
- while ( l <= r ){
- int mid = ( l + r ) >> 1;
- int last = 0, sum = 0;
- for ( i = 1; i <= n; i ++ ){
- if ( a[i]-last >= mid ) last = a[i];
- else sum ++;
- }
- if ( sum <= m ){ ret = mid; l = mid+1; }
- else r = mid-1;
- }
- printf ( "%d\n", ret );
- return 0;
- }
noip2015 子串
哇我去年居然会做这道题 然而我现在好像不会了..
$f_{i,j,k}$表示现在在第$i$块,小串匹配到$j$,大串匹配到$k$的方案数
然后就可以这样搞:$$f_{i,j,k}=\sum\limits_{p=0}^{k-1}f_{i-1,j-1,p}+f_{i,j-1,k-1}\times (s2[j-1]==s1[k-1])$$
那么对于前面的只要维护一个前缀和就可以了..
再给一道题吧,也是前缀和相关:CodeForces 587B 记得当年就是从这题吸取了经验的(感谢胖涛..)
- #include <cstdio>
- #include <cstring>
- #include <cstdlib>
- #include <algorithm>
- using namespace std;
- const int Maxn = 1010;
- const int Maxm = 210;
- const int Mod = 1000000007;
- char a[Maxn], b[Maxm];
- int n, m, K;
- int f[2][Maxm][Maxn];
- int main (){
- int i, j, k;
- scanf ( "%d%d%d", &n, &m, &K );
- scanf ( "%s", a+1 );
- scanf ( "%s", b+1 );
- int st = 0;
- for ( i = 0; i <= n; i ++ ) f[0][0][i] = 1;
- for ( k = 1; k <= K; k ++ ){
- st = st^1;
- memset ( f[st], 0, sizeof (f[st]) );
- for ( i = 1; i <= m; i ++ ){
- for ( j = 1; j <= n; j ++ ){
- if ( b[i] == a[j] ){
- f[st][i][j] = ( f[st][i][j] + f[st^1][i-1][j-1] ) % Mod;
- if ( b[i-1] == a[j-1] ) f[st][i][j] = ( f[st][i][j] + f[st][i-1][j-1] ) % Mod;
- }
- }
- }
- for ( i = 1; i <= m; i ++ ){
- for ( j = 1; j <= n; j ++ ) f[st][i][j] = ( f[st][i][j] + f[st][i][j-1] ) % Mod;
- }
- }
- printf ( "%d\n", f[st][m][n] );
- return 0;
- }
noip2015 运输计划
先预处理每条路径长度,找出最长的那条记为$ss$
二分答案,超过该答案的路径在树上差分标记一下,那么如果某个点子树所有标记和等于超过的路径数,证明该点与其父亲的边可能要割
然后在这些边中找到最大值,看$ss$减去这个值是否在二分的答案以内就行了
- #include <cstdio>
- #include <cstring>
- #include <cstdlib>
- #include <algorithm>
- using namespace std;
- const int Maxn = 300010;
- struct node {
- int y, next, d;
- }a[Maxn*2]; int first[Maxn], len;
- void ins ( int x, int y, int d ){
- len ++;
- a[len].y = y; a[len].d = d;
- a[len].next = first[x]; first[x] = len;
- }
- int n, m;
- int fa[Maxn][23], sum[Maxn][23], dep[Maxn];
- void dfs ( int x, int f ){
- for ( int i = 1; i <= 22; i ++ ){
- fa[x][i] = fa[fa[x][i-1]][i-1];
- sum[x][i] = sum[x][i-1] + sum[fa[x][i-1]][i-1];
- }
- for ( int k = first[x]; k; k = a[k].next ){
- int y = a[k].y;
- if ( y == f ) continue;
- fa[y][0] = x;
- sum[y][0] = a[k].d;
- dep[y] = dep[x]+1;
- dfs ( y, x );
- }
- }
- struct qnode {
- int x, y, lca, dist;
- }q[Maxn];
- void get_lca ( qnode &p ){
- int x = p.x, y = p.y;
- p.dist = 0;
- if ( dep[x] < dep[y] ) swap ( x, y );
- for ( int i = 22; i >= 0; i -- ){
- if ( dep[fa[x][i]] >= dep[y] ){
- p.dist += sum[x][i];
- x = fa[x][i];
- }
- }
- if ( x == y ){ p.lca = x; return; }
- for ( int i = 22; i >= 0; i -- ){
- if ( fa[x][i] != fa[y][i] ){
- p.dist += sum[x][i];
- p.dist += sum[y][i];
- x = fa[x][i];
- y = fa[y][i];
- }
- }
- p.dist += sum[x][0]+sum[y][0];
- p.lca = fa[x][0];
- }
- int bj[Maxn];
- int _max ( int x, int y ){ return x > y ? x : y; }
- int DFS ( int x, int f, int mid ){
- int ret = -1;
- for ( int k = first[x]; k; k = a[k].next ){
- int y = a[k].y;
- if ( y == f ) continue;
- ret = _max ( DFS ( y, x, mid ), ret );
- if ( bj[y] == mid ) ret = _max ( ret, a[k].d );
- bj[x] += bj[y];
- }
- return ret;
- }
- int main (){
- int i, j, k;
- scanf ( "%d%d", &n, &m );
- for ( i = 1; i < n; i ++ ){
- int x, y, d;
- scanf ( "%d%d%d", &x, &y, &d );
- ins ( x, y, d ); ins ( y, x, d );
- }
- dfs ( 1, 0 );
- int ss = 0;
- for ( i = 1; i <= m; i ++ ){
- scanf ( "%d%d", &q[i].x, &q[i].y );
- get_lca (q[i]);
- ss = _max ( ss, q[i].dist );
- }
- int l = 1, r = ss, ret;
- while ( l <= r ){
- int mid = ( l + r ) >> 1;
- int ssum = 0;
- for ( i = 1; i <= n; i ++ ) bj[i] = 0;
- for ( i = 1; i <= m; i ++ ){
- if ( q[i].dist > mid ){
- bj[q[i].x] ++; bj[q[i].y] ++;
- bj[q[i].lca] -= 2;
- ssum ++;
- }
- }
- if ( ss-DFS ( 1, 0, ssum ) <= mid ){ ret = mid; r = mid-1; }
- else l = mid+1;
- }
- printf ( "%d\n", ret );
- return 0;
- }
noip2013 华容道
记录f[i][j][k][l]为被标记的点在(i,j),空白点在k方向,使其移动到l方向的最小步数
这个东西是可以在$O(n^4)$预处理出来的
那么对于每一个询问,先算出空白点移动到标记点4个方向上的步数,然后就是最短路的事情了
推荐使用dijkstra算法,能够保证在$O(qn^2logn^2)$内算出..
- #include <cstdio>
- #include <cstring>
- #include <cstdlib>
- #include <algorithm>
- #include <queue>
- using namespace std;
- const int dx[4] = { 0, 1, -1, 0 };
- const int dy[4] = { 1, 0, 0, -1 };
- const int inf = 0x7fffffff;
- int f[35][35][4][4], num[35][35][4], tot;
- int dis[4010];
- bool v[35][35];
- int n, m, q;
- int dist[35][35]; bool bo[35][35];
- struct zb {
- int x, y;
- }e, s, t;
- void bfs1 ( int xx, int yy, int k ){
- queue <zb> q;
- for ( int i = 0; i <= n+1; i ++ ) for ( int j = 0; j <= m+1; j ++ ) dist[i][j] = inf, bo[i][j] = false;
- zb x;
- x.x = xx+dx[k]; x.y = yy+dy[k];
- q.push (x);
- dist[x.x][x.y] = 0; bo[x.x][x.y] = true;
- while ( !q.empty () ){
- x = q.front (); q.pop ();
- for ( int i = 0; i < 4; i ++ ){
- zb y;
- y.x = x.x+dx[i]; y.y = x.y+dy[i];
- if ( v[y.x][y.y] == false || bo[y.x][y.y] == true ) continue;
- dist[y.x][y.y] = dist[x.x][x.y]+1;
- bo[y.x][y.y] = true;
- q.push (y);
- }
- }
- for ( int i = 0; i < 4; i ++ ){
- f[xx][yy][k][i] = dist[xx+dx[i]][yy+dy[i]];
- }
- }
- void bfs2 (){
- queue <zb> q;
- for ( int i = 0; i <= n+1; i ++ ) for ( int j = 0; j <= m+1; j ++ ) dist[i][j] = inf, bo[i][j] = false;
- q.push (e);
- dist[e.x][e.y] = 0; bo[e.x][e.y] = true;
- while ( !q.empty () ){
- zb x = q.front (); q.pop ();
- for ( int i = 0; i < 4; i ++ ){
- zb y;
- y.x = x.x+dx[i]; y.y = x.y+dy[i];
- if ( v[y.x][y.y] == false || bo[y.x][y.y] == true ) continue;
- dist[y.x][y.y] = dist[x.x][x.y]+1;
- bo[y.x][y.y] = true;
- q.push (y);
- }
- }
- }
- struct node {
- int y, next, d;
- }a[160010]; int first[4010], len;
- void ins ( int x, int y, int d ){
- len ++;
- a[len].y = y; a[len].d = d;
- a[len].next = first[x]; first[x] = len;
- }
- struct knode {
- int x, dis;
- };
- bool operator < ( knode x, knode y ){ return x.dis > y.dis; }
- priority_queue <knode> Q;
- void dij (){
- while ( !Q.empty () ){
- knode x = Q.top (); Q.pop ();
- if ( dis[x.x] < x.dis ) continue;
- for ( int k = first[x.x]; k; k = a[k].next ){
- int y = a[k].y;
- if ( dis[y] > dis[x.x]+a[k].d ){
- dis[y] = dis[x.x]+a[k].d;
- knode p;
- p.x = y; p.dis = dis[y];
- Q.push (p);
- }
- }
- }
- }
- int _min ( int x, int y ){ return x < y ? x : y; }
- int main (){
- int i, j, k;
- scanf ( "%d%d%d", &n, &m, &q );
- for ( i = 1; i <= n; i ++ ){
- for ( j = 1; j <= m; j ++ ){
- int x;
- scanf ( "%d", &x );
- if ( x == 1 ) v[i][j] = true;
- }
- }
- tot = 0;
- for ( i = 1; i <= n; i ++ ){
- for ( j = 1; j <= m; j ++ ){
- if ( v[i][j] == false ) continue;
- for ( k = 0; k < 4; k ++ ){
- if ( v[i+dx[k]][j+dy[k]] == true ){
- v[i][j] = false;
- bfs1 ( i, j, k );
- v[i][j] = true;
- num[i][j][k] = ++tot;
- }
- else for ( int l = 0; l < 4; l ++ ) f[i][j][k][l] = inf;
- }
- }
- }
- while ( q -- ){
- scanf ( "%d%d%d%d%d%d", &e.x, &e.y, &s.x, &s.y, &t.x, &t.y );
- if ( s.x == t.x && s.y == t.y ){ printf ( "0\n" ); continue; }
- v[s.x][s.y] = false;
- bfs2 ();
- v[s.x][s.y] = true;
- for ( j = 1; j <= tot; j ++ ) first[j] = 0, dis[j] = inf;
- len = 0;
- for ( j = 0; j < 4; j ++ ){
- if ( dist[s.x+dx[j]][s.y+dy[j]] != inf ){
- knode p;
- p.x = num[s.x][s.y][j]; p.dis = dist[s.x+dx[j]][s.y+dy[j]];
- Q.push (p);
- dis[num[s.x][s.y][j]] = dist[s.x+dx[j]][s.y+dy[j]];
- }
- }
- for ( i = 1; i <= n; i ++ ){
- for ( j = 1; j <= m; j ++ ){
- for ( k = 0; k < 4; k ++ ){
- if ( v[i+dx[k]][j+dy[k]] == true ){
- for ( int l = 0; l < 4; l ++ ){
- if ( f[i][j][k][l] != inf ) ins ( num[i][j][k], num[i][j][l], f[i][j][k][l] );
- }
- ins ( num[i][j][k], num[i+dx[k]][j+dy[k]][3-k], 1 );
- }
- }
- }
- }
- dij ();
- int ans = inf;
- for ( i = 0; i < 4; i ++ ){
- if ( num[t.x][t.y][i] != 0 ) ans = _min ( ans, dis[num[t.x][t.y][i]] );
- }
- if ( ans != inf ) printf ( "%d\n", ans );
- else printf ( "-1\n" );
- }
- return 0;
- }
noip2011 选择客栈
一开始看错题了.. 做法其实没啥区别就是强行解释一下
由于题目给出的$p$是不会变的,然后就可以瞎搞处理了,时间复杂度是$O(k*小于等于p的节点数)$
- #include <cstdio>
- #include <cstring>
- #include <cstdlib>
- #include <algorithm>
- using namespace std;
- const int Maxc = 55;
- int c[Maxc], ans[Maxc];
- int n, K, p;
- int main (){
- int i, j, k;
- scanf ( "%d%d%d", &n, &K, &p );
- int anss = 0;
- for ( i = 1; i <= n; i ++ ){
- int fl, x;
- scanf ( "%d%d", &fl, &x );
- c[fl] ++;
- if ( x <= p ){
- for ( j = 0; j < K; j ++ ) ans[j] = c[j];
- }
- anss += ans[fl];
- if ( x <= p ) anss --;
- }
- printf ( "%d\n", anss );
- return 0;
- }
noip2012 开车旅行
由于两人决策唯一性,那么可以预处理出从某点开始走$2^i$步到达的点..
讲道理的话其实也就只需要处理$f_{i,0}$和$f_{i,1}$,后面的都可以倍增求
第一问就枚举点倍增搞
其他问就直接跑..
- #include <cstdio>
- #include <cstring>
- #include <cstdlib>
- #include <algorithm>
- #include <set>
- #define LL long long
- using namespace std;
- const int Maxn = 100010;
- const int inf = 0x7fffffff;
- struct no {
- int x, h;
- };
- bool operator < ( no x, no y ){ return x.h < y.h; }
- set <no> S;
- set <no> :: iterator it;
- int h[Maxn], n, m;
- int fa[Maxn][22], fb[Maxn][22], f[Maxn][22];
- no gob[Maxn];
- void pre (){
- int i, j, k;
- no p;
- p.x = n; p.h = h[n];
- S.insert (p);
- for ( i = n-1; i >= 1; i -- ){
- p.x = i; p.h = h[i];
- it = S.lower_bound (p);
- no fir, sec;
- fir.h = inf; sec.h = inf;
- if ( it != S.end () ){
- fir.x = (*it).x; fir.h = (*it).h-h[i];
- it ++;
- if ( it != S.end () ) sec.x = (*it).x, sec.h = (*it).h-h[i];
- it --;
- }
- if ( it != S.begin () ){
- it --;
- if ( h[i]-(*it).h <= fir.h ){
- sec = fir;
- fir.x = (*it).x; fir.h = h[i]-(*it).h;
- }
- else if ( h[i]-(*it).h <= sec.h ){
- sec.x = (*it).x; sec.h = h[i]-(*it).h;
- }
- if ( it != S.begin () ){
- it --;
- if ( h[i]-(*it).h <= sec.h ){
- sec.x = (*it).x; sec.h = h[i]-(*it).h;
- }
- }
- }
- if ( sec.h != inf ){
- f[i][0] = sec.x; f[i][1] = gob[sec.x].x;
- fa[i][0] = fa[i][1] = sec.h;
- fb[i][0] = 0; fb[i][1] = gob[sec.x].h;
- for ( j = 2; j <= 21 && i+(1<<(j-1)) <= n; j ++ ){
- f[i][j] = f[f[i][j-1]][j-1];
- fa[i][j] = fa[i][j-1] + fa[f[i][j-1]][j-1];
- fb[i][j] = fb[i][j-1] + fb[f[i][j-1]][j-1];
- }
- }
- if ( fir.h != inf ) gob[i] = fir;
- S.insert (p);
- }
- }
- struct node {
- int na, nb;
- };
- void gogogo ( int st, int xx, node &jl ){
- jl.na = jl.nb = 0;
- int i;
- for ( i = 21; i >= 0; i -- ){
- if ( fa[st][i]+fb[st][i] <= xx && f[st][i] != 0 ){
- jl.na += fa[st][i];
- jl.nb += fb[st][i];
- xx -= fa[st][i]+fb[st][i];
- st = f[st][i];
- }
- }
- }
- int main (){
- int i, j, k;
- scanf ( "%d", &n );
- for ( i = 1; i <= n; i ++ ) scanf ( "%d", &h[i] );
- pre ();
- int x0, s0;
- scanf ( "%d", &x0 );
- s0 = n; node ans, po;
- ans.na = ans.nb = 0;
- for ( i = n-1; i >= 1; i -- ){
- gogogo ( i, x0, po );
- if ( (LL)po.na*ans.nb < (LL)ans.na*po.nb || ( (LL)po.na*ans.nb == (LL)ans.na*po.nb && h[i] > h[s0] ) || s0 == n || ( ans.nb == 0 && po.nb != 0 ) ){
- s0 = i;
- ans = po;
- }
- }
- printf ( "%d\n", s0 );
- scanf ( "%d", &m );
- for ( i = 1; i <= m; i ++ ){
- int ss, xx;
- scanf ( "%d%d", &ss, &xx );
- gogogo ( ss, xx, po );
- printf ( "%d %d\n", po.na, po.nb );
- }
- return 0;
- }
noip2011 观光公交
记录$time_i$是到达$i$点的最小时刻,$last_i$是最迟一个到达$i$点的人的时刻
那么$time_i=\max(time_{i-1},last_{i-1})+d_i$
可以处理出修改每一个$d_i$所影响的人数
每次贪心找一个最大的减去就好了
时间复杂度是$O(nk)$的..
- #include <cstdio>
- #include <cstring>
- #include <cstdlib>
- #include <algorithm>
- using namespace std;
- const int Maxn = 100010;
- int time[Maxn], d[Maxn], last[Maxn];
- int n, m, K;
- struct lnode {
- int st, ed, t;
- }list[Maxn];
- int sum[Maxn], f[Maxn];
- int _max ( int x, int y ){ return x > y ? x : y; }
- int main (){
- int i, j, k;
- scanf ( "%d%d%d", &n, &m, &K );
- for ( i = 2; i <= n; i ++ ) scanf ( "%d", &d[i] );
- for ( i = 1; i <= m; i ++ ){
- scanf ( "%d%d%d", &list[i].t, &list[i].st, &list[i].ed );
- last[list[i].st] = _max ( last[list[i].st], list[i].t );
- sum[list[i].ed] ++;
- }
- time[1] = 0;
- for ( i = 2; i <= n; i ++ ){
- time[i] = _max ( time[i-1], last[i-1] ) + d[i];
- sum[i] += sum[i-1];
- }
- int ans = 0;
- for ( i = 1; i <= m; i ++ ){
- ans += time[list[i].ed] - list[i].t;
- }
- while ( K -- ){
- f[n] = n;
- for ( i = n-1; i >= 2; i -- ){
- if ( time[i] > last[i] ) f[i] = f[i+1];
- else f[i] = i;
- }
- int Max = 0, p;
- for ( i = 2; i <= n; i ++ ){
- if ( sum[f[i]]-sum[i-1] > Max && d[i] > 0 ){
- Max = sum[f[i]]-sum[i-1];
- p = i;
- }
- }
- ans -= Max; d[p] --;
- for ( i = 2; i <= n; i ++ ){
- time[i] = _max ( time[i-1], last[i-1] ) + d[i];
- }
- }
- printf ( "%d\n", ans );
- return 0;
- }
历年NOIP水题泛做的更多相关文章
- Atcoder 水题选做
为什么是水题选做呢?因为我只会水题啊 ( 为什么是$Atcoder$呢?因为暑假学长来讲课的时候讲了三件事:不要用洛谷,不要用dev-c++,不要用单步调试.$bzoj$太难了,$Topcoder$整 ...
- 历年NOIP真题总结
前言:最近把历年的NOIP真题肝了一遍(还有3个紫题先咕掉了),主要是到1998年的提高组的题.把题目的做题简要思路搁在这儿,一个是为了考前翻一翻,想想自己的哪些思路要梳理的什么什么的,反正怎么说呢, ...
- NOIP水题测试(2017082501)
日常水题测试又来了! 以后答案都以单题形式公布. 下面看今天的水题: 时间限制:5小时 题目一:无法形容的水 题目二:比上一题还水 题目三:一元三次方程求解 题目四:单词接龙 题目五:统计单词个数 题 ...
- NOIP水题测试(2017082401)
哈,水题测试又来了! 上次的水题简单吧! 答案是以单题形式发布的(旅行家的预算随后发布). 下面来看今天的题,还是水题. 时间限制:5小时 题目一:看上去就很水 题目二:比上面一题还水 题目三:数的划 ...
- 失踪的7(P1590&NOIP水题测试(2017082301))
题目链接:失踪的7 水题,不解释. #include<bits/stdc++.h> using namespace std; int main(){ int t; scanf(" ...
- 子数整数(P1151&NOIP水题测试(2017082301))
题目链接:子数整数 水题,不解释,自己看代码: #include<bits/stdc++.h> using namespace std; int main(){ int k; scanf( ...
- NOIP水题合集[3/未完待续]
NOIP2008pj传球游戏 题目描述 上体育课的时候,小蛮的老师经常带着同学们一起做游戏.这次,老师带着同学们一起做传球游戏. 游戏规则是这样的:n个同学站成一个圆圈,其中的一个同学手里拿着一个球, ...
- LCT裸题泛做
①洞穴勘测 bzoj2049 题意:由若干个操作,每次加入/删除两点间的一条边,询问某两点是否连通.保证任意时刻图都是一个森林.(两点之间至多只有一条路径) 这就是个link+cut+find roo ...
- NOIP水题测试(2017082301)
你们从题目也能看出来今天的题是很水的. 前几期答案还没出,效率有点低,谅解,谅解. 今天的答案应该会出的很快. 下面给题目: 时间限制:3小时 题目一:旅行家的预算 题目二:进制转换 题目三:乘积最大 ...
随机推荐
- 导出Excel通用工具类
导出Excel的两种方法: 一,POI 导入poi包 poi-3.11-beta3-20141111.jar /** * */ package com.car.ots.mpckp.utils; imp ...
- MySQL复制和集群
一.复制配置 (A) 主从服务器相同版本的数据库 (B) 主服务器上复制使用的账户,具有相应的权限. (C) 修改主服务器的配置文件my.cnf,开启BINLOG,并设置server-id的值.重启后 ...
- bzoj4692: Beautiful Spacing
先二分答案后dp 设\(su[n]\)为\(\sum_{1}^{n}xi[i]\) 设\(f[n]\)为1时表示第n个单次能做某一行的结尾,且之前的空格满足二分出来的答案. 考虑怎样的\(f[i]\) ...
- paxos(chubby) vs zab(Zookeeper)
参考: Zookeeper的一致性协议:Zab Chubby&Zookeeper原理及在分布式环境中的应用 Paxos vs. Viewstamped Replication vs. Zab ...
- Angular2 表单
1. 说明 表单是Web程序中的重要组成部分,构建良好以及实用的表单必须解决如下几个问题: (1). 如何跟踪及更新表单的数据状态 (2). 如何进行表单验证 (3). 如何显示表单验证信息 Angu ...
- 按钮button的css样式(扁平化底色)
.button { background-color: #ff0000; /* Green */ border: none; color: white; font-family:Arial; padd ...
- JSTL 操作符
el表达式的取值默认顺序: pageScope requestScope sessionScope applicationScope 结构,采用.导航,也称为存取器 ${us ...
- 八款常见的Android游戏引擎
原文地址:http://bbs.csdn.net/topics/380203732 1.Angle Angle是一款专为Android平台设计的,敏捷且适合快速开发的2D游戏引擎,基于OpenGL ...
- mina中游戏客户端服务端数据交互流程
====================================================================================CLIENT encode ...
- 破解myEclipse
建立一个java项目,将reg.java放入,并且运行在控制台 输入账户 回车就会出现 序列号 菜单栏--->myeclipse-->substription information--- ...