(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. luarocks install with lua5.1 and luajit to install lapis

    # in luarocks source directory...git clone https://github.com/archoncap/luarockscd luarocks ./config ...

  2. NGINX userid 分析、解码

    NGINX userid 分析.解码 生成userid的代码在 http/modules/ngx_http_userid_filter_module.c 大概550行左右. uid_set 是4个ui ...

  3. 【OpenStack】OpenStack系列17之OpenStack私有云设计一

    [软件系统] 1.操作系统(Minimal最小化安装): CentOS-6.6-x86_64,CentOS 6最后一个版本,官方建议版本. 相对于6.5版本: 强化对 SCSI 设备的处理,有助应付某 ...

  4. tcp/IP点对点通信程序

    点对点的通信 服务器端与客户端在建立连接之后创建一个进程 服务器端: 子进程用于接收主机的输入并将数据发送出去.父进程用于接收客户端的数据并输出到主机. 子进程一直等待主机的输入,输入的数据放在发送缓 ...

  5. MySQL数据丢失情况分析

    一.存储引擎层面丢失数据                                                       由于在实际项目中,我们往往使用支持事务的InnoDB存储引擎.我们 ...

  6. ubuntu tar 命令详细讲解

    Ubuntu--tar命令 tar zxvf ut6410-android2.1.tgz tar zcvf ut6410-android2.1.tgz ut6410-android2.1/ tar - ...

  7. WINDOWS xp用户账户怎么没了怎么办?

    这是因为系统的一个默认设置!新建用户会把管理员用户隐藏!只是修改了里面的注册表!在运行(windows徽标+R)里输入“regedit”可以打开注册表编辑器,定位到“HKEY_LOCAL_MACHIN ...

  8. iOS设备通知中心精品推荐消息删除

    如要彻底解决这个问题可以通过手机连接PC端91助手—功能大全—文件管理,进入/Library/MobileSubstrate/DynamicLibraries 文件夹,把AppSafety开头的文件都 ...

  9. Codeforces Round #321 (Div. 2)C(tree dfs)

    题意:给出一棵树,共有n个节点,其中根节点是Kefa的家,叶子是restaurant,a[i]....a[n]表示i节点是否有猫,问:Kefa要去restaurant并且不能连续经过m个有猫的节点有多 ...

  10. css div 清理浮动的2种方法

    使用float属性,导致div的内容发生浮动,浮动带来负影响: 1.背景不能显示 2.边框撑不开 3.div的padding和margin不能起作用: 处理float浮动的两种方式: 1.div的子类 ...