# NOIp2017 反思总结

## Day1

### T1

#include <bits/stdc++.h>
#define LL long long
using namespace std ;
int main() {
freopen ( "math.in", "r", stdin ) ;
freopen ( "math.out", "w", stdout ) ;
LL a, b ;
cin >> a >> b ;
cout << a*b-a-b << endl ;
return 0 ;
}
• 最终100pt

### T2

#include <bits/stdc++.h>
using namespace std ;
void File() {
freopen ( "complexity.in", "r", stdin ) ;
freopen ( "complexity.out", "w", stdout ) ;
}
const int maxm = 105 ;
int n, m, stk[maxm], top = 0 ;
char c[maxm], t[maxm], p[maxm] ;
bool vis[35] ;
int l[maxm], r[maxm], s[maxm], maxx[maxm] ;
void init() {
top = 0 ;
memset ( vis, 0, sizeof vis ) ;
memset ( s, 0, sizeof s ) ;
memset ( stk, 0, sizeof stk ) ;
memset ( l, 0, sizeof l ) ;
memset ( r, 0, sizeof r ) ;
memset ( maxx, 0, sizeof maxx ) ;
}
void solve() {
//puts("") ;
int i ;
bool ok = 1 ;
scanf ( "%d %s", &m, c+1 ) ;
for ( i = 1 ; i <= m ; i ++ ) {
scanf ( "%s", p+1 ) ;
if (p[1] == 'F') {
++top ;

scanf ( "%s", p+1 ) ;
if (vis[p[1]-'a']) {
//printf ( "%d %c\n", i, p[1] ) ;
ok = 0 ;
}
t[top] = p[1] ;
vis[p[1]-'a'] = 1 ;

scanf ( "%s", p+1 ) ;
s[top] = 0 ;
l[top] = r[top] = -1 ;
if (p[1] == 'n') s[top] = -1 ;
else l[top] = p[1]-'0' ;

scanf ( "%s", p+1 ) ;
if (p[1] == 'n') {
if (s[top] == -1) s[top] = 0 ;
else s[top] = 1 ;
}
else r[top] = p[1]-'0' ;

} else {
if (s[top] == -1) ;
else if (s[top] > 0) {
maxx[top-1] = max(maxx[top-1], s[top]+maxx[top]) ;
} else if (l[top] <= r[top]) maxx[top-1] = max(maxx[top-1], maxx[top]) ;
vis[t[top]-'a'] = 0 ;
maxx[top] = 0 ;
-- top ;
if (top < 0) {
//printf ( "%d top=%d\n", i, top ) ;
ok = 0 ;
}
}
//printf ( "top=%d s=%d maxx=%d\n", top, s[top], maxx[top] ) ;
}
//for ( i = 0 ; i <= m ; i ++ ) printf ( "t %d = %c\n", i, t[i] ) ;
//for ( i = 0 ; i < 30 ; i ++ ) if (vis[i]) printf ( "%c\n", i+'a' ) ;
if ((m&1) || ok==0 || top!=0) {
//printf ( "m=%d ok=%d top=%d\n", m, ok, top ) ;
puts("ERR") ;
return ;
}
//for ( i = 0 ; i <= m ; i ++ ) printf ( "%d s=%d maxx=%d\n", i, s[i], maxx[i] ) ;
int cc ;
if (c[3] == '1') cc = 0 ;
else {
for ( cc = 0, i = 1 ; !isdigit(c[i]) ; i ++ ) ;
for ( ; isdigit(c[i]) ; i ++ ) cc = cc*10 + c[i] - '0' ;
}
s[0] += maxx[0] ;
//printf ( "cc=%d s=%d\n", cc, s[0] ) ;
if (cc == s[0]) puts("Yes") ;
else puts("No") ;
}
int main() {
File() ;
int _ ;
scanf ( "%d", &_ ) ;
while (_--) {
init() ;
solve() ;
}
return 0 ;
}
• 最终90pt

#include <bits/stdc++.h>
using namespace std ;
void File() {
freopen ( "complexity.in", "r", stdin ) ;
freopen ( "complexity.out", "w", stdout ) ;
}
const int maxm = 105 ;
int n, m, stk[maxm], top = 0 ;
char c[maxm], t[maxm], p[maxm] ;
bool vis[35] ;
int l[maxm], r[maxm], s[maxm], maxx[maxm] ;
void init() {
top = 0 ;
memset ( vis, 0, sizeof vis ) ;
memset ( s, 0, sizeof s ) ;
memset ( stk, 0, sizeof stk ) ;
memset ( l, 0, sizeof l ) ;
memset ( r, 0, sizeof r ) ;
memset ( maxx, 0, sizeof maxx ) ;
}
void solve() {
int i, x, j, len ;
bool ok = 1 ;
scanf ( "%d %s", &m, c+1 ) ;
for ( i = 1 ; i <= m ; i ++ ) {
scanf ( "%s", p+1 ) ;
if (p[1] == 'F') {
++top ;
scanf ( "%s", p+1 ) ;
if (vis[p[1]-'a']) ok = 0 ;
t[top] = p[1] ;
vis[p[1]-'a'] = 1 ;
scanf ( "%s", p+1 ) ;
s[top] = 0 ;
l[top] = r[top] = -1 ;
if (p[1] == 'n') s[top] = -1 ;
else {
len = strlen(p+1) ;
x = p[1]-'0' ;
for ( j = 2 ; j <= len ; j ++ ) x = 10*x + p[j] - '0' ;
l[top] = x ;
}
scanf ( "%s", p+1 ) ;
if (p[1] == 'n') {
if (s[top] == -1) s[top] = 0 ;
else s[top] = 1 ;
}
else {
len = strlen(p+1) ;
x = p[1]-'0' ;
for ( j = 2 ; j <= len  ; j ++ ) x = 10*x + p[j] - '0' ;
r[top] = x ;
}
} else {
if (s[top] == -1) ;
else if (s[top] == 1) {
maxx[top-1] = max(maxx[top-1], 1+maxx[top]) ;
} else if (l[top] <= r[top]) maxx[top-1] = max(maxx[top-1], maxx[top]) ;
vis[t[top]-'a'] = 0 ;
maxx[top] = 0 ;
-- top ;
if (top < 0) ok = 0 ;
}
}
if ((m&1) || ok==0 || top!=0) {
puts("ERR") ;
return ;
}
int cc ;
if (c[3] == '1') cc = 0 ;
else {
for ( cc = 0, i = 1 ; !isdigit(c[i]) ; i ++ ) ;
for ( ; isdigit(c[i]) ; i ++ ) cc = cc*10 + c[i] - '0' ;
}
s[0] += maxx[0] ;
if (cc == s[0]) puts("Yes") ;
else puts("No") ;
}
int main() {
File() ;
int _ ;
scanf ( "%d", &_ ) ;
while (_--) {
init() ;
solve() ;
}
return 0 ;
}

- 最终20pt。
- 然而现在并没有改完，留坑。

## Day2

### T1

#include <bits/stdc++.h>
#define LL long long
using namespace std ;
void File() {
freopen ( "cheese.in", "r", stdin ) ;
freopen ( "cheese.out", "w", stdout ) ;
}
const LL maxn = 1050 ;
LL n, m, h, r ;
bool vis[maxn] ;
struct node {
LL x, y, z ;
} s[maxn] ;
LL dist ( node a, node b ) {
LL d = 0 ;
d = (a.x-b.x)*(a.x-b.x) ;
d += (a.y-b.y)*(a.y-b.y) ;
d += (a.z-b.z)*(a.z-b.z) ;
return d ;
}
queue <LL> Q ;
void init() {
memset ( vis, 0, sizeof vis ) ;
while (!Q.empty()) Q.pop() ;
}
void solve() {
LL i, x ;
r = r*r ;
for ( i = 1 ; i <= n ; i ++ )
if (s[i].z*s[i].z <= r) {
Q.push(i) ;
vis[i] = 1 ;
}
while (!Q.empty()) {
x = Q.front() ;
Q.pop() ;
for ( i = 1 ; i <= n ; i ++ )
if (vis[i] == 0&&dist(s[x], s[i]) <= 4*r) {
Q.push(i) ;
vis[i] = 1 ;
}
}

for ( i = 1 ; i <= n ; i ++ )
if (vis[i] && (s[i].z-h)*(s[i].z-h) <= r) {
puts("Yes") ;
return ;
}
puts("No") ;
}
int main() {
File() ;
LL i, _ ;
scanf ( "%lld", &_ ) ;
while (_--) {
init() ;
scanf ( "%lld%lld%lld", &n, &h, &r ) ;
for ( i = 1 ; i <= n ; i ++ )
scanf ( "%lld%lld%lld", &s[i].x, &s[i].y, &s[i].z ) ;
solve() ;
}
return 0 ;
}
• 最终得分100pt

### T2

f[x][d][S]$f[x][d][S]$ 表示以点x$x$为根，到赞助商距离为d$d$，点集为S$S$的这棵子树的最小代价。顺便记下树的边权和。

mmp，最后出来才发现这是正解？？？没有什么优化就交了？？？

#include <bits/stdc++.h>
#define LL long long
using namespace std ;
void File() {
freopen ( "treasure.in", "r", stdin ) ;
freopen ( "treasure.out", "w", stdout ) ;
}
const LL maxn = 15, maxS = (1<<12)+5, zhf = 1e9 ;
LL n, m, g[maxn][maxn], f[maxn][maxn][maxS] ;
LL bt[maxS], v[maxn][maxn][maxS] ;
bool have ( LL s, LL x ) {
s >>= x-1 ;
return s&1 ;
}
LL check_min ( LL &a, LL b ) { return a = a<b? a:b ; }

int main() {
File() ;
LL rec, d, i, j, S, s, s1, s2, x, u ;
scanf ( "%lld%lld", &n, &m ) ;
S = (1<<n)-1 ;
for ( i = 0 ; i <= n ; i ++ )
for ( j = 0 ; j <= n ; j ++ ) {
g[i][j] = zhf ;
for ( s = 0 ; s <= S ; s ++ )
f[i][j][s] = zhf ;
}
for ( i = 1 ; i <= m ; i ++ ) {
scanf ( "%lld%lld%lld", &x, &u, &rec ) ;
check_min(g[x][u], rec) ;
g[u][x] = g[x][u] ;
}

bt[0] = 0 ;
for ( i = 1 ; i <= S ; i ++ ) bt[i] = bt[i>>1]+(i&1) ;

for ( i = 1 ; i <= n ; i ++ )
for ( j = 0 ; j <= n ; j ++ )
f[i][j][1<<(i-1)] = 0 ;

int bit ;
for ( bit = 2 ; bit <= n ; bit ++ )
for ( s = 0 ; s <= S ; s ++ ) {
if (bt[s] != bit) continue ;
for ( s1 = 0 ; s1 <= S ; s1 ++ ) {
if (bt[s1]==0 || bt[s1] >= bit) continue ;
s2 = s^s1 ;
if ((s1&s2)!=0 || (s1|s2)!=s) continue ;
for ( x = 1 ; x <= n ; x ++ ) {
if (have(s1,x)==0) continue ;
for ( u = 1 ; u <= n ; u ++ ) {
if (have(s2,u)==0) continue ;
if (g[x][u] == zhf) continue ;
for ( d = 1 ; d <= n ; d ++ ) {
rec = f[x][d-1][s1] + f[u][d][s2] + d*g[x][u] ;
if (f[x][d-1][s] > rec) {
f[x][d-1][s] = rec ;
v[x][d-1][s] = v[x][d-1][s1] + v[u][d][s2] + g[x][u] ;
} else if (f[x][d-1][s] == rec) {
check_min(v[x][d-1][s], v[x][d-1][s1]+v[u][d][s2]+g[x][u]) ;
}
}
}
}
}
}

LL ans = zhf ;
for ( i = 1 ; i <= n ; i ++ )
check_min(ans, f[i][0][S]) ;
printf ( "%lld\n", ans ) ;
return 0 ;
}
• 最终得分80pt。

- 最终得分30pt

(￣▽￣)

## After All

• 最终得分420，全省排名44。
考试的时候坑自己，两天T2煮熟的鸭子都飞了。（雾）
考试的时候心态明显没有平常好，考前20min还在床上？（大雾）
不过考试的时候会发挥低于正常水平也是意料之中的事情，都过去了也不要再多说了。

• 接下来干什么？有些迷茫，先搞搞文化休息一下脑袋吧。
现在的化学课都成了美术课了，还有翻生物、化学书就像字典？？？

• 不打算退组，但是这个星期也不打算停课。
不如颓颓文化，某些人说的好听点是要冲冬令营实际上不就是在逃避文化课？

• 和猫还有赛克做了下ACM北京的同步赛，我就是去搞笑（混饭吃）的？
代码能力奇差。

• 准备趁这点时间把不会的东西都学了，但是绝对不能把脑袋做傻。
换了个座位，在机房少搞颓。
坐在fastest旁边感觉快到模糊，瞎写了几道杜教筛。
还把redbag赶到一边去了，（然而她似乎并没有怼我

11-23:逃课搞竞赛被抓，偷鸡不成蚀把米，很不爽2333