(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. [flag飞起]

    重度Flag: Rush 未来程序・改 (note: 由于代码存放地址原因(物理)无法本周完成) 轻度Flag: 未来程序・改写完后刷QTREE与主席树 严重Flag: 计算几何...

  2. BZOJ 1452 [JSOI2009] Count

    这道题好像有点简单的样子... absi找题目好厉害啊...确实是一道比较裸的2dBIT啊. 水掉吧. 附:2dBIT怎么做: 2dBIT就是BIT套BIT啦. 所以修改loop(x+=lowbit( ...

  3. IOC原理解释

    spring ioc它其实是一种降低对象耦合关系的设计思想,通常来说,我们在一个类调用另一个类的方法的时候,需要不断的new新的对象来调用该方法,类与类之间耦合度比较高,有了ioc容器以后,ico容器 ...

  4. JavaScript设计模式 - 单例模式

    单例模式:保证一个类仅有一个实例,并提供一个访问它的全局访问点. 一.实现一个标准的单例模式,用一个变量来标志当前是否已经为某个类创建过对象, 如果是,则在下一次获取该对象实例时,直接返回之前创建的对 ...

  5. mac OS X 安装svn

    因为从10.5版本开始适用Mac OS,SVN一直都是默认安装的软件. 后来发现一个简单的办法. 如果你有安装XCode,只需要在code > Preferences > download ...

  6. CSS“反转”为LESS

    LESS(官网在此:http://lesscss.net/)的魅力相信大家都已明了,个人认为它最大的魅力在于能够清晰的展现嵌套关系. 针对现有的项目,它的应用难点主要在于—— 何时转换为css,即是否 ...

  7. Redis笔记(二)Redis的部署和启动

    Linux下Redis的部署和启动 下载安装介质 Redis官网地址:http://www.redis.io/目前最新版本是redis-3.0.3. 可以访问 http://download.redi ...

  8. Spring中的设计模式学习

    Spring提供了一种Template的设计哲学,包含了很多优秀的软件工程思想. 1. 简单工厂 又叫做静态工厂方法(StaticFactory Method)模式,但不属于23种GOF设计模式之一. ...

  9. device unauthorized & ANDROID_ADB_SERVER_PORT 问题解决

    最近做安卓开发的时候,碰到了如下两个极品问题,刚开始晕头转向,仔细一研究终于解决了: FAQ1: C:\Users\xxx>adb shelladb: Env var ANDROID_ADB_S ...

  10. Jil序列化JSON

    使用Jil序列化JSON提升Asp.net web api 性能   JSON序列化无疑是Asp.net web api 里面性能提升最重要的一环. 在Asp.net web api 里面我们可以插入 ...