(wzj这蒟蒻终于滚Cu了,今天第一题SB题写+调用了1.5h,测试时还WA了一个点。第二题数位DP20分钟写完遇到鬼打墙,中间一切正常最后输出一坨负数。调了1h发现是一个数组开小了。又花了20+min写暴力对拍,大概拍了拍感觉没问题交上去就爆零了2333.最后一道题花10min写个暴力,然后开始写正解,然后,然后,然后写完了却没有调完,最后只能交暴力结果暴力3WA6T,只有10分2333.)

---------------------------------------------------------------------------

T1: http://oj.cnuschool.org.cn/oj/home/problem.htm?problemID=497

这是一个博弈游戏,我们可以考虑将当前的n,m记到状态,但可行的(n,m)可能很大,怎么办呢?

注意当m>1时,n最多到sqrt(c)也就是35000+,而当m=1时我们手动分析即可,时间复杂度即为O(sqrt(c)*logc)。

怎么处理Draw的情况呢?注意只有初始n=1且(n+1)^m>=c时两人都不会加n,于是就平局了。(开始这里没有想清楚WA了一个点)

实现时可以看我的code也可以看std的code。我的code用了一个辅助数组t[i]表示最大的指数使i^(t[i])<c来加速判断,相比之下std的可能更好理解。

我的code:

#include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
#define rep(s,t) for(int i=s;i<=t;i++)
using namespace std;
inline int read() {
int x=,f=;char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=-;
for(;isdigit(c);c=getchar()) x=x*+c-'';
return x*f;
}
typedef long long LL;
int c,f[][],vis[][];
LL qpow(int n,int m) {
LL ans=,t=n;
while(m) {
if(m&) ans*=t;
t*=t;m>>=;
}
return ans;
}
int t[];
void init() {
memset(t,,sizeof(t));memset(vis,,sizeof(vis));
t[]=c;rep(,) while(qpow(t[i]+,i)<=c) t[i]++;
}
int dp(int n,int m) {
if(n>t[m]) return ;
if(n>t[]) return (c-n)&;
if(n>t[m+]) return (t[m]-n)&;
int& ans=f[n][m];if(vis[n][m]) return ans;
vis[n][m]=;
if(n+<=t[m]&&!dp(n+,m)) return ans=;
if(n<=t[m]+&&!dp(n,m+)) return ans=;
return ans=;
}
int main() {
int T=read();
while(T--) {
int n=read(),m=read();c=read()-;init();
if(n==&&qpow(,m)>c) puts("Draw");
else printf("%s\n",dp(n,m)?"Alice":"Bob");
}
return ;
}

std的code:

#include <cmath>
#include <cstdio>
#include <cstring> using namespace std; const double eps = 1e-;
const int MAXA = , MAXB = ; int set[MAXA][MAXB];
int a, b, n, ret; int solve(int a, int b){
if (a < MAXA && b < MAXB && set[a][b] != ) return set[a][b] - ;
bool A = false, B = false;
if (log(n)/log(a + ) - eps > b) A = true;
if (pow((double)a, b + ) < n - eps) B = true;
int ret = ;
if (!A && !B){
ret = -;
} else if (a == && !A){
ret = ;
} else if (b == && !B){
ret = ((n - a) & ) ? - : ;
} else {
ret = ;
if (B){
int tmp = solve(a, b + ); if (tmp < ret) ret = tmp;
}
if (A){
int tmp = solve(a + , b); if (tmp < ret) ret = tmp;
}
if (ret != ) ret = -ret;
}
if (a < MAXA && b < MAXB) set[a][b] = ret + ;
return ret;
} void print()
{
if (ret == ) printf("Alice\n");
else if (ret == -) printf("Bob\n");
else printf("Draw\n");
} int main()
{
int T;
scanf("%d", &T);
while (T --){
scanf("%d%d%d", &a, &b, &n);
memset(set, , sizeof(set));
ret = solve(a, b);
print();
}
return ;
}

T2:http://oj.cnuschool.org.cn/oj/home/problem.htm?problemID=498

题意很裸,数位DP。然而我这个蒟蒻在此之前只写过一次数位DP,写起来真是23333.

60分的做法:设f[len][front][sum1][sum2]表示长度为len,开头为front,奇数位之和为sum1,偶数位之和为sum2的方案,转移什么的自己YY或看我的code吧。

加快速度还可以用g[len][front][k]表示长度为len,开头为front,奇数位与偶数位的gcd不超过k的方案。(不过这显然没有什么卵用,我还在这里开小了数组调了1h)

询问考虑差分,将f(l--r)转成f(r)-f(l-1)。考虑之前确定的位对下面没确定的位造成的影响,这个可以看看我的code具体体会。

最后我cal(x)实际求的是[1,x)的幸运数,然后,然后,然后,然后,然后,然后就爆零了。

#include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
#define rep(i,s,t) for(int i=s;i<=t;i++)
using namespace std;
inline int read() {
int x=,f=;char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=-;
for(;isdigit(c);c=getchar()) x=x*+c-'';
return x*f;
}
typedef long long LL;
LL f[][][][],fx[][][];
LL g[][][],xp[];
int preg[][];
int gcd(int a,int b) {return !b?a:gcd(b,a%b);}
void init() {
xp[]=;rep(i,,) xp[i]=xp[i-]*;
rep(i,,) f[][i][i][]=;
rep(i,,) rep(j,,) rep(sum1,,i*) rep(sum2,,i*-sum1) {
if(!f[i][j][sum1][sum2]) continue;
if(!(i&)) rep(k,,) f[i+][k][sum1+k][sum2]+=f[i][j][sum1][sum2];
else rep(k,,) f[i+][k][sum1][sum2+k]+=f[i][j][sum1][sum2];
}
rep(sum1,,) rep(sum2,,) preg[sum1][sum2]=gcd(sum1,sum2);
rep(i,,) rep(j,,) rep(sum1,,i*) rep(sum2,,i*-sum1) {
int t=preg[sum1][sum2];
g[i][j][t]+=f[i][j][sum1][sum2];
}
rep(i,,) rep(j,,) rep(k,,) g[i][j][k]+=g[i][j][k-];
}
int bit[],k;
LL cal(LL x) {
memset(bit,,sizeof(bit));
LL t=x,ans=;int len=,s1=,s2=;
while(t) bit[++len]=t%,t/=;
rep(i,,len-) rep(j,,) ans+=g[i][j][k];
for(int i=len;i;i--) {
rep(j,,bit[i]-) {
if(!j&&i==len) continue;
rep(sum1,,*i) rep(sum2,,*i-sum1)
if(sum1+s1&&sum2+s2&&preg[sum1+s1][sum2+s2]<=k) ans+=f[i][j][sum1][sum2];
}
if(i&) s1+=bit[i];else s2+=bit[i];
}
return ans;
}
int main() {
init();int T=read();
while(T--) {
k=read();LL l,r;
scanf("%lld%lld",&l,&r);
printf("%lld\n",cal(r+)-cal(l));//cal(r)-cal(l-1) -> WA0 + 2333333
}
return ;
}

100分的做法:设f[len][k][sum1][sum2]表示还有i位没有填写,已填写的与len同奇偶的数位和为sum1,不同奇偶的数位和为sum2,gcd(sum1,sum2)<=k的方案。

f[len][k][sum1][sum2]=sigma{f[len-1][k][sum2-d][sum1]|d=[0,9]},这样询问时就很快了。

注意这里的cal求的是[1,x]

#include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
#define rep(i,s,t) for(int i=s;i<=t;i++)
using namespace std;
inline int read() {
int x=,f=;char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=-;
for(;isdigit(c);c=getchar()) x=x*+c-'';
return x*f;
}
typedef long long LL;
const int maxk=;
LL f[][maxk][maxk][maxk];
int gcd(int a,int b) {return !b?a:gcd(b,a%b);}
void init() {
rep(i,,maxk-) rep(j,,maxk-) rep(k,gcd(i,j),maxk-) f[][k][i][j]=;
rep(i,,) rep(k,,maxk-) {
int mx=(-i)/*;
rep(a,,mx) rep(b,,mx) rep(d,,min(b,)) f[i+][k][b-d][a]+=f[i][k][a][b];
}
}
int bit[],k;
LL cal(LL x) {//[1,x]
if(x<=) return ;
LL t=x,ans=;int len=,s1=,s2=;
while(t) bit[++len]=t%,t/=;
for(int i=len;i;i--) {
rep(j,,bit[i]-)
if(i&) ans+=f[i-][k][s1][s2+j];
else ans+=f[i-][k][s2][s1+j];
if(i&) s2+=bit[i];else s1+=bit[i];
}
return ans+f[][k][s1][s2];
}
int main() {
init();int T=read();
while(T--) {
k=min(read(),);LL l,r;
scanf("%lld%lld",&l,&r);
printf("%lld\n",cal(r)-cal(l-));//notice!
}
return ;
}

T3:http://oj.cnuschool.org.cn/oj/home/problem.htm?problemID=499

这是一个比较常规的数据结构题目,首先我们要会求一条链上有多少还没有被删去的点,这个我们可以用DFS序+线段树完成。其次我们发现这道题还带有可持久化操作,那就用可持久化线段树来维护每个版本的DFS序,那么求一条链上有多少还没有被删去的点就成为O(logn)的了。然后我们对于每个询问需要判断被询问点在lca--x上还是在lca--y上,然后二分判断,时间复杂度O(log^2)。

说起来简单写起来还是相当复杂的(我还没写完),先放上std与神犇lxt的AC代码。

std:

#include <vector>
#include <cstdio>
#include <algorithm> using namespace std; const int MAXD = ;
const int MAXN = ; vector <int> adj[MAXN];
bool type[MAXN];
int anc[MAXN][MAXD];
int n, m, root; void init()
{
scanf("%d", &n);
for (int i = ; i <= n; i ++){
scanf("%d", &anc[i][]);
if (!anc[i][]) root = i;
else adj[anc[i][]].push_back(i);
}
} int lt[MAXN], rt[MAXN], dep[MAXN];
bool col[MAXN];//state
int stack[MAXN]; void dfs()
{
int tail = , cnt = ; stack[tail] = root;
while (tail){
int u = stack[tail];
if (!col[u]){
lt[u] = ++ cnt; dep[u] = dep[anc[u][]] + ;
int ts = adj[u].size();
for (int i = ; i < ts; i ++)
stack[++ tail] = adj[u][i];
for (int d = ; d < MAXD; d ++)
anc[u][d] = anc[anc[u][d-]][d-];
col[u] = ;
} else {
rt[u] = ++ cnt; tail --;
}
}
} struct Tseg{
Tseg *lc, *rc;
int l, r, sum;
} pool[MAXN << ]; Tseg *nxt(){
static int cur = ;
return &pool[cur ++];
} Tseg *pos[MAXN], *cur, *lat; #define l(t) (t->lc)
#define r(t) (t->rc) void mktree(Tseg *t, int ll, int rr){
t->l = ll, t->r = rr, t->sum = ;
if (ll == rr) return;
int mid = (ll + rr) >> ;
l(t) = nxt(); mktree(l(t), ll, mid);
r(t) = nxt(); mktree(r(t), mid+, rr);
} #define t_ch tree_change Tseg *t_ch(Tseg *t, int p, int c){
Tseg *ret = nxt(); *ret = *t;
if (t->l == t->r){
ret->sum = c; return ret;
}
if (p <= l(t)->r) l(ret) = t_ch(l(t), p, c);
else r(ret) = t_ch(r(t), p, c);
ret->sum = l(ret)->sum + r(ret)->sum;
return ret;
} int fa(int x, int deep){
if (dep[x] == deep) return x;
for (int d = MAXD-; d >= ; d --)
if (dep[anc[x][d]] >= deep) x = anc[x][d];
return x;
} int find_lca(int x, int y){
if (dep[x] > dep[y]){
int t = x; x = y; y = t;
}
if (dep[x] < dep[y]) y = fa(y, dep[x]);
for (int d = MAXD-; d >= ; d --)
if (anc[x][d] != anc[y][d]) x = anc[x][d], y = anc[y][d];
if (x == y) return x;
return anc[x][];
} #define t_s tree_sum int t_s(Tseg *t, int l, int r){
if (t->l == l && t->r == r) return t->sum;
if (r <= l(t)->r) return t_s(l(t), l, r);
if (l >= r(t)->l) return t_s(r(t), l, r);
return t_s(l(t), l, l(t)->r) + t_s(r(t), r(t)->l, r);
} int check(int x, int y){
return dep[y] - dep[x] + - (t_s(cur, lt[x], lt[y]) - t_s(lat, lt[x], lt[y]));
} int kth(int x, int y, int k){
if (check(x, y) < k) return -;
int l = dep[x], r = dep[y];
while (l < r){
int mid = (l + r) >> ;
int v = fa(y, mid);
int s = check(x, v);
if (s >= k) r = mid;
else l = mid + ;
}
return fa(y, l);
} void print()
{
dfs();
pos[] = nxt(); mktree(pos[], , n << );
scanf("%d", &m);
int type, a, b, c, k, y;
for (int i = ; i <= m; i ++){
scanf("%d", &type);
if (type == ){
scanf("%d", &c);
Tseg *tmp = t_ch(pos[i-], lt[c], );
pos[i] = t_ch(tmp, rt[c], -);
} else {
scanf("%d%d%d%d", &a, &b, &k, &y);
pos[i] = pos[i-]; cur = pos[i]; lat = pos[y];
if (a == anc[b][] || b == anc[a][]){//no castles
puts("-1"); continue;
}
int lca = find_lca(a, b), ans = -;
if (lca != a && lca != b){
int u = anc[a][], v = anc[b][];
int sum = check(lca, u);
if (sum >= k) ans = kth(lca, u, sum - k + );
else ans = v == lca ? - : kth(fa(v, dep[lca] + ), v, k - sum);
} else {
int u, v;
if (lca == a){
u = fa(b, dep[a]+), v = anc[b][];
} else {
u = fa(a, dep[b]+), v = anc[a][];
int sum = check(u, v);
if (sum < k) {puts("-1"); continue;}
k = sum - k + ;
}
ans = kth(u, v, k);
}
printf("%d\n", ans);
}
}
} int main()
{
freopen("travel.in", "r", stdin);
freopen("travel.out", "w", stdout);
init();
print();
return ;
}

lxt:

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <map>
#define MAXN 200005
#define MAXT 10000005
using namespace std;
int read(){
int ret = ; char c = getchar();
while(c < '' || c > '') c = getchar();
while(c >= '' && c <= '') {ret *= ; ret += c - ''; c = getchar();}
return ret;
}
int Root, ee, head[MAXN], n, m, fat[MAXN], A, B;
struct Edge{int to, next;}edge[MAXN];
inline void addedge(int x, int y){edge[++ ee].to = y; edge[ee].next = head[x]; head[x] = ee;}
int dep[MAXN], din[MAXN], dout[MAXN], dd, skip[MAXN][];
int dfs(int x){
dep[x] = dep[fat[x]] + ;
din[x] = ++ dd;
skip[x][] = fat[x];
for(int i = ; i <= ; i ++) skip[x][i] = skip[skip[x][i - ]][i - ];
for(int i = head[x]; i != -; i = edge[i].next) dfs(edge[i].to);
dout[x] = ++ dd;
}
int finddep(int x, int dd){
if(dep[x] == dd) return x;
for(int i = ; i >= ; i --) if(dep[skip[x][i]] >= dd) x = skip[x][i];
return x;
}
int cnt, root[MAXN], cl[MAXT], cr[MAXT], s[MAXT];
void insert(int &x, int pre, int l, int r, int p, int c){
x = ++ cnt;
cl[x] = cl[pre], cr[x] = cr[pre], s[x] = s[pre] + c;
if(l == r) return;
int mid = l + r >> ;
if(mid >= p) insert(cl[x], cl[pre], l, mid, p, c);
else insert(cr[x], cr[pre], mid + , r, p, c);
}
int ask(int t, int l, int r, int L, int R){
if(L > R) return ;
if(l >= L && r <= R) return s[t];
int mid = l + r >> , ret = ;
if(L <= mid) ret = ask(cl[t], l, mid, L, R);
if(R >= mid + ) ret += ask(cr[t], mid + , r, L, R);
return ret;
}
inline int LCA(int x, int y){
if(dep[x] < dep[y]) swap(x, y);
for(int i = ; i >= ; i --) if(dep[skip[x][i]] >= dep[y]) x = skip[x][i];
for(int i = ; i >= ; i --) if(skip[x][i] != skip[y][i]) x = skip[x][i], y = skip[y][i];
if(x == y) return x; return skip[x][];
}
int count(int x, int y){
return dep[y] - dep[x] + - ask(B, , * n, din[x], din[y]) + ask(A, , * n, din[x], din[y]);
}
int calck(int x, int y, int k){
if(count(x, y) < k) return -;
int l = dep[x], r = dep[y];
while(l != r){
int mid = l + r >> ;
if(count(x, finddep(y, mid)) >= k) r = mid;
else l = mid + ;
} return finddep(y, l);
}
int main(){
freopen("travel.in", "r", stdin);
freopen("travel.out", "w", stdout);
n = read();
memset(head, -, sizeof(head));
for(int i = ; i <= n; i ++) {fat[i] = read(); if(fat[i]) addedge(fat[i], i); else Root = i;}
dfs(Root);
m = read();
for(int tt = ; tt <= m; tt ++){
int key; key = read();
if(key == ){
int c; scanf("%d", &c);
int la;
insert(la, root[tt - ], , * n, din[c], );
insert(root[tt], la, , * n, dout[c], -);
}else{
root[tt] = root[tt - ];
int a, b, k, y; a = read(); b = read(); k = read(); y = read();
A = root[y], B = root[tt];
if(a == fat[b] || b == fat[a]) {puts("-1"); continue;}
int lca = LCA(a, b);
if(lca != a && lca != b){
int aa = count(lca, fat[a]);
if(aa >= k) {printf("%d\n", calck(lca, fat[a], aa - k + )); continue;}
if(fat[b] == lca) {puts("-1"); continue;}
printf("%d\n", calck(finddep(b, dep[lca] + ), fat[b], k - aa));
} else{
if(lca == a) { printf("%d\n", calck(finddep(b, dep[a] + ), fat[b], k)); continue;}
int la = finddep(a, dep[b] + );
int aa = count(la, fat[a]);
if(aa < k) {puts("-1"); continue;}
printf("%d\n", calck(la, fat[a], aa - k + ));
}
}
}
// system("pause");
return ;
}

BJOI2015 Day3的更多相关文章

  1. 冲刺阶段day3

    day3 项目进展 今天周三,我们五个人难得的一整个下午都能聚在一起.首先我们对昨天的成果一一地查看了一遍,并且坐出了修改.后面的时间则是做出 登录界面的窗体,完善了登录界面的代码,并且实现了其与数据 ...

  2. BZOJ 4337: BJOI2015 树的同构 树hash

    4337: BJOI2015 树的同构 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=4337 Description 树是一种很常见的数 ...

  3. python笔记 - day3

    python笔记 - day3 参考:http://www.cnblogs.com/wupeiqi/articles/5453708.html set特性: 1.无序 2.不重复 3.可嵌套 函数: ...

  4. python_way,day3 集合、函数、三元运算、lambda、python的内置函数、字符转换、文件处理

    python_way,day3 一.集合 二.函数 三.三元运算 四.lambda 五.python的内置函数 六.字符转换 七.文件处理 一.集合: 1.集合的特性: 特性:无序,不重复的序列 如果 ...

  5. Spark菜鸟学习营Day3 RDD编程进阶

    Spark菜鸟学习营Day3 RDD编程进阶 RDD代码简化 对于昨天练习的代码,我们可以从几个方面来简化: 使用fluent风格写法,可以减少对于中间变量的定义. 使用lambda表示式来替换对象写 ...

  6. Spark Tungsten揭秘 Day3 内存分配和管理内幕

    Spark Tungsten揭秘 Day3 内存分配和管理内幕 恭喜Spark2.0发布,今天会看一下2.0的源码. 今天会讲下Tungsten内存分配和管理的内幕.Tungsten想要工作,要有数据 ...

  7. Catalyst揭秘 Day3 sqlParser解析

    Catalyst揭秘 Day3 sqlParser解析 今天我们会进入catalyst引擎的第一个模块sqlparser,它是catalyst的前置模块. 树形结构 从昨天的介绍我们可以看到sqlPa ...

  8. Kakfa揭秘 Day3 Kafka源码概述

    Kakfa揭秘 Day3 Kafka源码概述 今天开始进入Kafka的源码,本次学习基于最新的0.10.0版本进行.由于之前在学习Spark过程中积累了很多的经验和思想,这些在kafka上是通用的. ...

  9. python s12 day3

    python s12 day3   深浅拷贝 对于 数字 和 字符串 而言,赋值.浅拷贝和深拷贝无意义,因为其永远指向同一个内存地址. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ...

随机推荐

  1. sharepoint部件webparth关闭找回的方法

  2. maven项目 Java compiler level does not match the version of the installed Java project facet

    因工作的关系,Eclipse开发的Java项目拷来拷去,有时候会报一个很奇怪的错误.明明源码一模一样,为什么项目复制到另一台机器上,就会报“java compiler level does not m ...

  3. sybaseIQ索引类型和使用注意事项

    1. FP(Fast Projection)此索引为默认的索引形式,在创建表时系统自动设置此索引. 特点:用于SELECT.LIKE '%sys%'.SUM(A+B).JOIN操作等语句. 此类型索引 ...

  4. Java for LeetCode 187 Repeated DNA Sequences

    All DNA is composed of a series of nucleotides abbreviated as A, C, G, and T, for example: "ACG ...

  5. ubuntu命令行相关命令使用心得

    一.Ubuntu解压缩zip,tar,tar.gz,tar.bz2 ZIP zip可能是目前使用得最多的文档压缩格式.它最大的优点就是在不同的操作系统平台,比如Linux, Windows以及Mac ...

  6. JavaScript封装成类

    JavaScript在WEB编程中能起到很大的作用,将一些常用的功能写成JavaScript类库. 将下面代码保存为Common.js 类库功能: 1.Trim(str)--去除字符串两边的空格 2. ...

  7. Express4--说明

    express4.*;(1) var app = express(): 生成一个express实例 app. (2) app.set('views', path.join(__dirname, 'vi ...

  8. Maximum sum(poj 2479)

    题意:给一段数列,将这个数列分成两部分,使两部分的最大子段和的和最大,输出和 /* 看数据没想到是(O)n的算法,求出从前向后的最大子段和和从后向前的最大子段和, 然后枚举断点. 第一次提交不小心折在 ...

  9. Struts2中配置默认Action

    1.当访问的Action不存在时,页面会显示错误信息,可以通过配置默认Action处理用户异常的操作:2.配置方法:    在struts.xml文件中的<package>下添加如下内容: ...

  10. 【ACM - 搜索模板】

    [广搜模板] #include <iostream> #include <stdio.h> #include <string.h> #include <que ...