早上坐了 2 2 个小时的车到了义乌中学,送走了本校另一批学生,中午在义乌中学吃了中饭,然后下午在车上背了背ISAP I S A P 和多项式相关( NOIP N O I P 模拟赛欸,怎么会考 qwq q w q )。
晚上在国际学术交流中心(好像在长沙理工听过这个名字)的餐厅吃 15 15 块钱的便餐(诡异的餐厅装饰),成功 Get G e t 一晚上的休息时间。
早上一去就是先是看了看机房,发现机房电脑配置不错( i5−6500 i 5 − 6500 + 8GB 8 G B 内存),就是分辨率 1600∗900 1600 ∗ 900 ( wtf w t f ?)然而机房的联想硬盘保护并没有关,于是瞎搞用硬盘启动了一发 Ubuntu18.04 U b u n t u 18.04 ,然后发现有线网络居然崩了?
好了就只是不能愉快地使用 VSCode V S C o d e 而已。
上午是 hzq h z q (去年 ZJOI Z J O I 一试虐场选手)
讲图论(从精通到)入门,然后我看到 AntiQuality A n t i Q u a l i t y 在前台欸!
hzq h z q 讲课虽然是简单的知识(大佬很亲民啊),但是却能变通出许多题目,比如说有如下知识点:
有可能数据结构(一般是线段树)优化建图,给定 Ai,j A i , j 向建 Ai+1,j A i + 1 , j 图,我们可以加入一个点然后就可以把 O(N2) O ( N 2 ) 的边数优化成 O(N) O ( N ) 的了。
(这个在具体数学里有),可以搞下有环的概率DP(莫名其妙套进图论):例如 limn→∞∑nj=1qj=11−q lim n → ∞ ∑ j = 1 n q j = 1 1 − q 。
然后被建议说是正权不要写 SPFA S P F A 要写 Dijkstra D i j k s t r a +高效率的堆或者线段树。
看到二叉堆优化 Dijkstra D i j k s t r a 有 O((N+M)∗log2N) O ( ( N + M ) ∗ l o g 2 N ) 的超高复杂度又想到斐波那契堆的恐怖我果断放弃。
下午讲题我模仿度教的神奇 for f o r 循环被 d d 了(反正我写的代码不是给别人看的)?
例题:
https://www.luogu.org/problemnew/show/P1967
http://poj.org/problem?id=3028
https://www.lydsy.com/JudgeOnline/problem.php?id=2725
Easy: E a s y :
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1815
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1443
https://www.lydsy.com/JudgeOnline/problem.php?id=1064
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1705
https://www.luogu.org/problemnew/show/P1983
Hard: H a r d :
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1340
https://www.lydsy.com/JudgeOnline/problem.php?id=1924
https://www.luogu.org/problemnew/show/P3953
表示在学校里只能过掉 2 2 题。
熟悉的学长,不熟悉的课。
今天hzq h z q 讲了树上问题入门。
既然是树上问题,自然要比图上问题简单一个层次(吗?)
首先是熟悉的树链剖分,这个的话 ZJOI2008 Z J O I 2008 出过裸题树的统计(我怎么这么想用主席树艹过去呢)。
突然觉得是不是可以进 10 10 年前的 D D 类+了?
对了早上去的时候还补了一下昨天的Tarjan T a r j a n 求割点、割边,和熟悉的求强连通分量相比:
好吧其实没有 ETT E T T 的,只不过是 Euler E u l e r 序而已,发现 Euler E u l e r 序的入度出度都记的策略不仅仅用在树上莫队(近乎淘汰却可以作为暴力使用的算法),还有 LCA L C A 配合 ETT E T T 使用 +1−1RMQ + 1 − 1 R M Q 也是一个及其优美的运用,反正可以做到 O(n)−O(1) O ( n ) − O ( 1 ) 的优秀 LCA L C A 以及通过笛卡尔树转化成 LCA L C A 的普通 RMQ R M Q (即不满足 +1−1 + 1 − 1 性质的 RMQ R M Q )。
然后得出结论, LCA=RMQ L C A = R M Q (雾)。
听说 LCT L C T 和 ETT E T T 配合食用效果更加?(虽然 log22n>log2n l o g 2 2 n > l o g 2 n 效果不是很好,但是 Wiki W i k i 上看到 TopTree T o p T r e e 有操作是 log42n l o g 2 4 n 甚至是 log52n l o g 2 5 n ,果然是 300+ 300 + 行大怪物)
听说 TarjanLCA T a r j a n L C A 不用学,听说我们写的并查集是 log2n l o g 2 n 的?
今天看了看按秩合并+路径压缩的并查集感觉并不难写,反阿克曼函数才是玄学。
这个其实不难写,像树形背包什么的想法简单就是代码实现有点烦,状态容易推错,然后样例过了最终凉凉(希望考试的时候别写挂就好了)。
插一句,突然想到洛谷的动态 dp d p 模板题可以用数据结构维护带修改 dp d p ,上课也提到了这个想法。
一般会叫做基环外向树,然后其实就是枚举成环的点(或边)的选择情况,然后对剩下的树进行树形 dp d p 即可,如果加上虚树优化就可以将复杂度中的乘法优化成加法,比如说 HNOI2018 H N O I 2018 就有一题毒瘤就是这类题目的省选版。(听说这题在 HNOI2018 H N O I 2018 是中等题?)
还做了一道题 [ZJOI2014] [ Z J O I 2014 ] 骑士,这题居然是我自己完全不看题解做出来了的?一定是假的题。
首先有 dp d p 的转移方程 F[x][i+j]+=F[x][i]+F[son[k]][j] F [ x ] [ i + j ] + = F [ x ] [ i ] + F [ s o n [ k ] ] [ j ] ,乍一看像是 O(n3) O ( n 3 ) 的复杂度,其实发现 i+j i + j 就是从子树的两个部分枚举点,然后只会在他们的 LCA L C A 也就是 x x 上产生贡献,故复杂度与点对的数量同级,也就是O(n2) O ( n 2 ) 。
例题
https://www.lydsy.com/JudgeOnline/problem.php?id=4539
https://www.lydsy.com/JudgeOnline/problem.php?id=1217
https://www.lydsy.com/JudgeOnline/problem.php?id=3626
Easy: E a s y :
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1299
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1677
https://www.lydsy.com/JudgeOnline/problem.php?id=1036
https://www.lydsy.com/JudgeOnline/problem.php?id=4033
Hard: H a r d :
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1709
https://www.lydsy.com/JudgeOnline/problem.php?id=1040
今天一去就考试,然后凉凉。
考试的时候一看 T1 T 1 ,咦?
这题目什么意思?
写了个暴力其实是正解,然后发现样例什么永远是答案的两倍,而且我居然 20 20 分钟没有看出来?
尴尬。。。
然后瞬间“秒”掉 T2 T 2 ,果然是一个找循环的水题?
T2 T 2 先不对拍了,先搞了一波 T3 T 3 ,第一遍看了下题目感觉自己能 AK A K ?
1h 1 h 后:神奇的 T3 T 3 ,主席树套 KD−Tree K D − T r e e ?感觉人二维数据结构没写过多少啊?
蒟蒻弱弱地向评论区的 Dalao D a l a o 发问,维护矩形 Max M a x 和矩形求和的二维数据结构怎么写?
T2 T 2 对拍:什么一拍一个错啊,发现想法错了,预处理方法有问题,无奈只能转为暴力预处理。
T3 T 3 暴力花了 3min 3 m i n 打好,然后就耐心检查 (yy ( y y 数据结构 ) ) 。。。
考试最后10 10 分钟突然发现 T1 T 1 居然用的是 Ans/2 A n s / 2 ,紧急改成 Ans∗2−1(mod1000000007) A n s ∗ 2 − 1 ( m o d 1000000007 ) 。
并列 rk2 r k 2 ?果然是暴力出奇迹。。。
考完前一下发现 T2 T 2 其实可以做到同复杂度预处理的,打脸。
实际上就是求 ∑u∑v∗dis(u,v) ∑ u ∑ v ∗ d i s ( u , v ) 枚举每条边算左右两边的标号之和,从而计算这条边的贡献即可
大手子用 O(nlog) O ( n l o g ) 过了首先把序列分成 n/gcd(n,m) n / g c d ( n , m ) 块,两个位置只有满足 x x 才有可能遇到对于 k k 整除lcm(n,m) l c m ( n , m ) 的部分可以直接处理,因为这个时候第一个 AI A I 的序列中一个位置假如又能遇到第二个 AI A I 序列中的位置 A A ,又能遇到位置B B ,那么遇到 A A 和遇到B B 的次数一定是相等的,所以可以快速统计。然后就是剩下的部分,这个时候有一个性质, k/n<=m k / n <= m 换而言之每个位置最多被用 O(n) O ( n ) 次。我们不妨对第一个位置算出这 O(n) O ( n ) 次它遇到的都是什么情况,从而计算出这个位置对答案的贡献。举个例子 n=3,m=7 n = 3 , m = 7 第二个序列中第一个位置假如会遇到 、、、、、1、3、2、1、3、2 、 、 、 、 、 1 、 3 、 2 、 1 、 3 、 2 ,那么往后推一格,可以得到第三个位置遇到的是 、、、、、3、2、1、3、2、1 、 、 、 、 、 3 、 2 、 1 、 3 、 2 、 1 。这样我们在头删去一个,尾加入一个,可以 O(1) O ( 1 ) 维护会遇到什么情况,由于 n/gcd(n,m) n / g c d ( n , m ) 和 m/gcd(m,n) m / g c d ( m , n ) 互质,我们这样扫一遍一定可以扫到所有位置。注意轮数不同的细节需要处理。
这个题可以主席树可以树套树可以莫队可以st表可以倍增,怎么搞怎么能过,无非是能接受的数据范围是多少。首先不难想到哈夫曼树,用哈夫曼树可以轻松求出l,r在什么情况下满足l到r的最小值是 xi x i 不难发现对于每组询问,我们要求的是 ∑i=ri=l(i−max(Li,l)+1)(min(r,Ri)−i+1)xi ∑ i = l i = r ( i − m a x ( L i , l ) + 1 ) ( m i n ( r , R i ) − i + 1 ) x i 其中 Li,Ri L i , R i 表示最大的满足区间最大值是 xi x i 的区间,可以用单调栈求出。注意建树时需要强制优先级,即防止相等时出现区间相交的情况。这个时候老练的选手可以发现,我们写一个三维数据结构,就可以通过 70p 70 p 更老练的选手可以发现,我们可以用可持久化去掉一个 log l o g 拿到 90 90 但是暴力算到这里就推不下去了,我们需要考虑哈夫曼树的性质。首先哈夫曼树的中序遍历就是原序列。然后哈夫曼树的 lca l c a 就是区间 max m a x 再者哈夫曼树的深度没有保证。观察哈夫曼树不难发现,从l向上一直爬,爬到 l l 和r r 的 lca l c a ,假如某个点是它父亲的左儿子,那么它父亲一定在 (l,r) ( l , r ) 区间内,而且它父亲的 L L 一定小于等于l l ,反方向考虑,如果某个点不在这条树链上,那么它的 L L 一定大于l l , r r 那侧也同理可以推出类似的结论。到这里一个初步的想法形成了,把每个点都按照(i−Li+1)(Ri−i+1)xi ( i − L i + 1 ) ( R i − i + 1 ) x i 计算,然后再算两条树链的贡献。前者可以用序列前缀和实现,后者可以在树上用前缀和的形式存储,注意 LCA L C A 是两条树链的交所以要特殊处理。复杂度瓶颈在求 LCA L C A ,其他都是 O(n) O ( n ) 的那么 O(n)LCA O ( n ) L C A ?
今天还把 Windows W i n d o w s 下的 .vscode . v s c o d e 配置好了,开心。
今天休息,颓废了一天。
一个上午的紫荆花之恋调试(一个留了 3 3 个月的坑)。
还是没有结果(弃掉),RE85 R E 85 最后在数据下发现是由于 WA W A 导致的强制在线出错以致于 RE R E 。
贴下代码 (RE85) ( R E 85 ) :
#include
#include
const int maxm=105,maxn=100005,maxe=200005,maxp=20000005,tt=1000000000;
inline void read(int &Res){
char ch=getchar();
for (Res=0;!isdigit(ch);ch=getchar());
for (;isdigit(ch);ch=getchar()) Res=(Res<<3)+(Res<<1)+ch-48;
}
inline void Upd_mx(int &x,int y){if (y>x) x=y;}
struct DACT_Tag{
struct ScapeGoatTree{
int SonRoot[maxn],RootRoot[maxn],stk[maxp],top,tmp[maxn],cnt,tot,now_p,flg,val,sum;
struct Ad{int x,siz,l,r;}T[maxp];
inline void Create(int &p,int val){T[p=top?stk[top--]:++tot]=(Ad){val,1,0,0};}
void DFS(int p){
stk[++top]=p;
if (T[p].l) DFS(T[p].l);
tmp[++cnt]=T[p].x;
if (T[p].r) DFS(T[p].r);
}
void Build(int L,int R,int &p){
if (L>=R) return Create(p,tmp[L]);
int mid=(L+R)>>1;
T[Create(p,tmp[mid]),p].siz=R-L+1;
if (L^mid) Build(L,mid-1,T[p].l);
if (mid^R) Build(mid+1,R,T[p].r);
}
inline void ReBuild(int root,int &p){
cnt=0,DFS(root),flg=1;
for (int i=1;i<=cnt;++i) if (tmp[i]>=val){
for (int j=++cnt;j>i;--j) tmp[j]=tmp[j-1];
tmp[i]=val,flg=0;
break;
}
if (flg) tmp[++cnt]=val;
Build(1,cnt,p);
}
void Insert(int &p){
if (!p) return Create(p,val);
++T[p].siz;
if (val5>(T[p].siz<<2)?ReBuild(p,p):Insert(T[p].l);
else T[T[p].r].siz*5>(T[p].siz<<2)?ReBuild(p,p):Insert(T[p].r);
}
void Query(int p){
if (!p) return;
if (valelse Query(T[p].r),sum+=T[T[p].l].siz+1;
}
void Restore(int p){
stk[++top]=p;
if (T[p].l) Restore(T[p].l);
if (T[p].r) Restore(T[p].r);
}
inline void RootClear(int p){if (RootRoot[p]) Restore(RootRoot[p]),RootRoot[p]=0;}
inline void SonClear(int p){if (SonRoot[p]) Restore(SonRoot[p]),SonRoot[p]=0;}
inline void RootInsert(int p,int v){val=v,Insert(RootRoot[p]);}
inline void SonInsert(int p,int v){val=v,Insert(SonRoot[p]);}
inline int RootQuery(int p,int v){return val=v,sum=0,Query(RootRoot[p]),sum;}
inline int SonQuery(int p,int v){return val=v,sum=0,Query(SonRoot[p]),sum;}
inline void Give(int x,int y){SonRoot[y]=SonRoot[x],SonRoot[x]=0;}
}F;
struct Tree{
int dep[maxn],pre[maxn],dist[maxn][maxm],siz[maxn],home[maxn],lnk[maxn],nxt[maxe],son[maxe],stk[maxe],top,tot,now_tmp;
inline void Add(int x,int y){nxt[now_tmp=top?stk[top--]:++tot]=lnk[x],son[lnk[x]=now_tmp]=y;}
inline void Clear(int x){for (int j=lnk[x];j;j=nxt[j]) stk[++top]=j; lnk[x]=0;}
}T;
int N,cnt,root,r[maxn],lnk[maxn],nxt[maxe],son[maxe],len[maxe],tot,siz[maxn],w[maxn],frm,frmdepth;
bool vis[maxn];
inline void Add(int x,int y,int z){nxt[++tot]=lnk[x],son[lnk[x]=tot]=y,len[tot]=z;}
inline void Init(int x,int y){T.Add(0,0),w[0]=(N=x)+1,F.RootInsert(1,-(r[T.dep[1]=1]=y));}
void DFS(int p){
++cnt,vis[p]=1;
for (int j=T.lnk[p];j;j=T.nxt[j]) DFS(T.son[j]);
}
void GetRoot(int p,int fa,int cnt){
siz[p]=1,w[p]=0;
for (int j=lnk[p];j;j=nxt[j]) if ((son[j]^fa)&&(vis[son[j]])) GetRoot(son[j],p,cnt),siz[p]+=siz[son[j]],Upd_mx(w[p],siz[son[j]]);
if (Upd_mx(w[p],cnt-siz[p]),w[p]void RecalSize(int p,int fa){
siz[p]=1;
for (int j=lnk[p];j;j=nxt[j]) if ((son[j]^fa)&&vis[son[j]]) RecalSize(son[j],p),siz[p]+=siz[son[j]];
}
void Recal(int p,int fa,int dis){
++T.siz[frm],T.dist[p][frmdepth]=dis,F.RootInsert(frm,dis-r[p]),F.SonInsert(root,dis-r[p]);
for (int j=lnk[p];j;j=nxt[j]) if ((son[j]^fa)&&vis[son[j]]) Recal(son[j],p,dis+len[j]);
}
void Work(int p,int depth,int tot){
T.Clear(p),vis[p]=0,T.dep[p]=depth,F.RootClear(p),F.RootInsert(p,-r[p]),RecalSize(p,0),T.siz[p]=1,T.dist[p][depth]=0;
for (int j=lnk[p];j;j=nxt[j]) if (vis[son[j]]) root=0,GetRoot(son[j],0,siz[son[j]]),F.SonClear(root),frm=p,frmdepth=depth,Recal(son[j],p,len[j]);
for (int j=lnk[p];j;j=nxt[j]) if (vis[son[j]]) root=0,GetRoot(son[j],0,siz[son[j]]),T.Add(T.pre[root]=p,root),T.home[root]=T.lnk[p],Work(root,depth+1,siz[son[j]]);
}
inline void ReBuild(int p){cnt=0,DFS(p),root=0,GetRoot(p,0,cnt),T.son[T.home[p]]=root,T.pre[root]=T.pre[p],F.Give(p,root),Work(root,T.dep[p],cnt);}
inline int Insert(int p,int x,int y,int z){
Add(p,x,y),Add(x,p,y),r[p]=z,T.siz[p]=1,T.pre[p]=x,T.Add(x,p),T.home[p]=T.lnk[x],T.dist[p][T.dep[p]=T.dep[x]+1]=0,F.RootInsert(p,-z);
int now=p,lst=now,ReRoot=0,Ans;
for (int i=T.dep[p]-1;i;--i){
lst=now,++T.siz[now=T.pre[now]],F.RootInsert(now,(T.dist[p][i]=T.dist[x][i]+y)-z),F.SonInsert(lst,T.dist[p][i]-z);
if (T.siz[lst]*5>(T.siz[now]<<2)+5) ReRoot=now;
}
if (ReRoot) ReBuild(ReRoot);
Ans=F.RootQuery(p,z)-1,now=p,lst=now;
for (int i=T.dep[p]-1;i;--i) lst=now,now=T.pre[now],Ans+=F.RootQuery(now,z-T.dist[p][i])-F.SonQuery(lst,z-T.dist[p][i]);
return Ans;
}
}DACT;
int N,T;
long long Ans;
int main(){
read(T),read(N),read(T),read(T),read(T),DACT.Init(N,T),puts("0");
for (int i=2,x,y,z;i<=N;++i) read(x),read(y),read(z),x^=Ans%tt,printf("%lld\n",Ans+=DACT.Insert(i,x,y,z));
return 0;
}
一个下午的毒瘤,这种枚举成环边的状压 DP D P 居然用虚树优化,直接将多次树形 DP D P 的乘法优化为加法,果然是省选级的 TG T G 题。
但是晚上这个坑还没补完。。。
hzq h z q 继续讲课,今天讲的是(简单?)数据结构。
其实是挺简单的,今天讲的甚至都是 PJ P J 的数据结构,突然发现 ZS Z S 给我们做过多少 TG T G 的题目没告诉我们了。
其实上面讲 TarjanLCA T a r j a n L C A 的时候提过,总共就是两种写法,然后按照道理的话,做到反 Ackermman A c k e r m m a n 函数的 O(α(N)) O ( α ( N ) ) 的并查集不兹磁维护集合信息的操作,所以我们就不采用按秩合并,仅仅路径压缩,然后后我们就可以再开一个数组来记录我们所需要的当前节点和当前根关系的信息。
这里当然是普通的二叉堆,其实 TG T G 组没有 Fibnacci F i b n a c c i 堆那样的神奇东西。但今天第一次发现了原来二叉堆也可以写替换元素啊,但是常数巨大,据说还有 pushdown p u s h d o w n 和 pushup p u s h u p ,建议使用数组记录一下,用到时若该元素已有标记那么久直接删除(常用套路),然后还有 K K 确定或者单调的动态全局第K K 大。
快入左偏树神教来!
单调队列其实就是用来优化形如如下形式的 DP D P 的:
Fi=Max(Fi−k)+wi F i = M a x ( F i − k ) + w i ,并且满足 0<k≤pi 0 < k ≤ p i ,并有 pi p i 单调不增。
这个显然很好做啊, que[head]<i−pi q u e [ h e a d ] < i − p i 删除头部, F[i]=F[que[tail]]+w[i] F [ i ] = F [ q u e [ t a i l ] ] + w [ i ] ,然后 F[que[tail]]>F[i] F [ q u e [ t a i l ] ] > F [ i ] 删除尾部,成功做到了均摊 O(1) O ( 1 ) 。
然后单调栈用啦求离当前点最近的某些大小关系信息。
比如说极大化:以前我就用单调栈写,真的省了很多代码,还省了空间。
这个就是预处理出最高高度 Height[] H e i g h t [ ] ,然后用每行左右两次单调栈维护出每个点的最大扩展区域即可。
我居然成功调试好了毒瘤,至此, HNOI2018 H N O I 2018 已经被我全部订正完毕!
完结撒花。
课件:
http://poj.org/problem?id=1988
https://www.lydsy.com/JudgeOnline/problem.php?id=2006
Easy: E a s y :
https://www.lydsy.com/JudgeOnline/problem.php?id=1057
https://www.luogu.org/problemnew/show/P2827
https://www.lydsy.com/JudgeOnline/problem.php?id=1029
http://codeforces.com/problemset/problem/799/B
Hard: H a r d :
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1303
http://codeforces.com/problemset/problem/725/d
我果然是太菜了。
十年 OI O I 一场空, NOIP N O I P 见祖宗。
我不会告诉你今天又有一场比赛了的。
今天去了就没睡醒,然后考试开始 [10,210] [ 10 , 210 ] 分钟之内睡觉了 [3,200] [ 3 , 200 ] 分钟。
今天 T1 T 1 我推了个错误的结论,然后对拍出错了(感谢 Windows W i n d o w s 给我再生之力), Get100 G e t 100 分。
然后 T2 T 2 就没看懂题意了,幸好有一大批人和我一样觉得题目有问题(走法的问题),题目 update u p d a t e 我居然没有看懂(晕)。
T3 T 3 的话我想了半天硬是没想到数位 DP D P ,哈?数位题被我想成分块?
花了 30+min 30 + m i n 去卡常数,然后发现最大点永远是大约 5.9 5.9 秒,想到评测机那样的老爷机,也就最终弃掉。
考完: mmp m m p 感觉全世界都 A A 掉了T2 T 2 ,咦,怎么都写得那么奇怪,果然是我题意理解错了。
这场居然有好多人 AK A K 了?我大概是睡太香了什么都不知道吧。
(听说看见 250 250 是基准分?果然是优秀的贪心。。。)
对了还有一个小插曲:第一次评完发现全场 T3 T 3 没分, T2 T 2 最高 50 50 ,然后 hzq h z q 终于发现了一个惊天大秘密。
其实就是数据造错了。
但是好多人 AK A K 那是实在话,果然是%%%。
下午就听 dalao d a l a o 上去切题,说:这道不是傻逼题吗?
一个排列可以视作若干个环。
不难发现一个长度为n的环需要 n−1 n − 1 次操作使得所有数回到原来位置。
所以找出所有环,答案就是 n− n − 环的数量。
一个结论是对兔子来说最优策略是直接跑向终点然后在终点等狼。
因为假如一只兔子可以袭击到狼,那么它可以尾行狼接近终点的时候再发动袭击,两者是等价的。
那么也就是说任何一种情况一定不会比最优策略的情况优。
因为两者速度相同,所以狼的任何回避都是没有意义的。
然后把所有兔子按照到终点的顺序排个序然后逐个判断即可。
不难发现价值就是 log10AixorAj l o g 10 A i x o r A j 。
由于 xor x o r 基于 2 2 进制的,但是答案计算是基于十进制的,乍一看非常难以计算。
分析一下答案,以2 2 为例, [10,99] [ 10 , 99 ] 区间答案都是 2 2 。
假如我们确定了AixorAj A i x o r A j 的前几位,是不是就能确定答案?
比如假如确定了 64 64 这一位是 1,32 1 , 32 这一位是 0 0 ,那么范围就是[64,96) [ 64 , 96 ) 。
不难发现这个时候答案一定是 2 2 ,换而言之我们不关心后面的几位是什么。
那么一个初步的想法就是在01 01 字母树上爬(本质和数位 DP D P 相同),一层层爬下去,记录 Ai A i 和 Aj A j 分别在哪个节点。
然后就过了。
为什么会这样?
假设最坏情况,即所有可能的 Ai A i 都出现了一次。
不难发现我们只会在答案确定的情况下产生贡献,也就是截止状态。
而这种情况答案的区间左右端点要么是由 10 10 进制的边界决定的,要么是由2进制的边界决定的,而区间与区间之间必然是互不重叠的。
那么十进制产生的边界是 O(log10Ai) O ( l o g 10 A i ) 的,二进制产生的边界是 O(log2Ai) O ( l o g 2 A i )
那么总区间数不难发现也是 O(logAi) O ( l o g A i ) 的。
根据某个清华大手子分析,复杂度是 O(logA2i) O ( l o g A i 2 ) 常数很小。
但是 01 01 字母树的作用和直接线性扫一遍是无异的,不过 01 01 字母树好理解也好写一些。
今天 NOI N O I 线上同步赛一试,果然我连暴力分都打不全。
按照常理,暴力分 75+24+12=111 75 + 24 + 12 = 111 ,我连暴力都没有打满。
我的分数: 40+12+0=52 40 + 12 + 0 = 52 ,成功没拿到暴力分的一半。
考试开始 10min 10 m i n :咦怎么着网站怎么也进不去啊?
成功在 15min 15 m i n 拿到题目。
开场先开 T2 T 2 ,鬼知道我怎么想的。
3h 3 h 过后: Woc W o c , T2 T 2 的 44pts 44 p t s 状压怎么一推一个挂啊?完了这辈子写不来状压 DP D P 了。
(突然想起了 HNOI2018 H N O I 2018 那个诡异的 N≤15 N ≤ 15 部分分,我居然连状压都没看出来?)
完了只会 12pts 12 p t s 的大暴力。
T1 T 1 我直接一遍题意, 20min 20 m i n 打完代码,样例怎么错了?
问问旁边的人得知原来 0 0 边是只能与起点直接或间接相连啊!
10min 10 m i n 改完代码(细节真多),然后多组数据没清空!
树和离线的情况口胡出来了,然后就已经来不及打了。
为了代码不超过 200 200 行,就不分这么多 SubTask S u b T a s k 了。
T3 T 3 花了 10min 10 m i n 打好暴力,又调了一下好久没写的字符串 Hash H a s h ,感觉稳过?
最后全机房听取 WA W A 声一片。
T3 T 3 看到别人 O(Q∗N4) O ( Q ∗ N 4 ) 或者 O(Q∗N3∗log2N) O ( Q ∗ N 3 ∗ l o g 2 N ) 的暴力 TLE T L E 了,然后我一个 O(Q∗N3) O ( Q ∗ N 3 ) 的暴力 WA W A 了,我为什么要打字符串 Hash H a s h 啊,有什么用吗?
考完听说 T1 T 1 是可持久化并查集,果然我只会写 ext/rope e x t / r o p e 版本的,然而 O(NN−−√) O ( N N ) 的复杂度并不能接受,所以我理所应当地没有想到(巧妙的找理由)。
发现其实仅仅带撤销(本题需要的)的可持久化按秩合并并查集其实 O(N∗log2N) O ( N ∗ l o g 2 N ) 的复杂度就可以实现了,果然是我太菜了。
pb p b _ ds d s 虽好用,可不要偷懒哦。
感觉这几天每天早上都没睡醒啊,晚上 10 10 点左右就睡了,感觉我一定是想回家好好睡一个懒觉了。
今天继续讲课,复杂 dp d p ?简单数据结构 → → 复杂 dp d p ?惊叹 hzq h z q 神一般的逻辑。
首先计算了一下状态数,这个需要用到组合数学的知识。
貌似就是一个乘法原理和加法原理的事情?
然后就引出了今天的重点之一:
最常见的就是枚举该位选或者不选的 2n 2 n 的最朴素的状态压缩 DP D P ,这个的话 NOIP2016 N O I P 2016 有愤怒的小鸟这道题是史上最水的 Day1T3 D a y 1 T 3 了。
然后状态压缩 DP D P 的多进制情况可能就需要一些技巧或者是转化才能可以 AC A C ,比如说 NOIP2017 N O I P 2017 宝藏,这题的 DP D P 方程及其优化不是一般的繁琐,根据奇技淫巧或许可以做到 O(4n∗n227) O ( 4 n ∗ n 2 27 ) 或者是按照标算一样打 O(3n∗n) O ( 3 n ∗ n ) 。
然而上面的题解都太烦,如果是 NOIP N O I P 遇到这种小数据的题目实在推不出来,我们可以使用带剪枝的 DFS D F S 实现 O(n!∗n?) O ( n ! ∗ n ? ) 的 0ms 0 m s 满分,或者是超纲的模拟退火实现 O(k∗n2) O ( k ∗ n 2 ) 的随机 Prim P r i m ,错误的想法不总是错误,多刷几遍就对了(有后效性的 DP D P 都这么干)。
这个的话就很常见了,记得最早的时候 ZS Z S 给我们做的 [ZJOI2010] [ Z J O I 2010 ] 数字统计(那时我们居然都不知道这道题是省选题),就是典型,通过枚举每一位的信息得出某种结论就是这种题目优化暴力的精髓。
其实这题的数据可以再放大, 1012 10 12 实在太小了,应该像 ZS Z S 给我们做的另外一道数位 DP D P 一样做到惊人的 N≤1050000 N ≤ 10 50000 。
这个的话就很有意思了,题目比较多,也不好列举。
比如说鏼爷出的集训队互测题加强版。
问有多少个n的排列的最长上升子序列是给出的序列。
这题里面 n≤35 n ≤ 35 ,整整比原题 n≤12 n ≤ 12 大了3倍!
最终题解说是可以做到 O(3n3) O ( 3 n 3 ) ,神奇的复杂度。
具体的我也听得一脸懵逼。
课件:
https://www.luogu.org/problemnew/show/P3959
https://www.lydsy.com/JudgeOnline/problem.php?id=1799
https://www.lydsy.com/JudgeOnline/problem.php?id=3591
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1221
Easy: E a s y :
https://www.lydsy.com/JudgeOnline/problem.php?id=1076
https://www.lydsy.com/JudgeOnline/problem.php?id=1087
https://www.lydsy.com/JudgeOnline/problem.php?id=3209
https://www.lydsy.com/JudgeOnline/problem.php?id=1833
Hard: H a r d :
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1569
https://www.lydsy.com/JudgeOnline/problem.php?id=4762
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1775
今天是 NOI N O I 同步赛 Day2 D a y 2 ,我第一次口头 AC A C 了 NOI N O I 题诶!
T1 T 1 真心是挺简单的,但是我的数论知识真心不过关。。。
显然可以把题目中的描述转化为 ATK∗x−Pi∗y=0 A T K ∗ x − P i ∗ y = 0 这样一群二元一次不定方程。
然后我们可以解出的 x x 一定可以满足x=kz+b x = k z + b 的形式(其中必须满足 k∈N∗ k ∈ N ∗ , z∈N z ∈ N ),这个显然可以利用 exgcd() e x g c d ( ) 求出来,然后便可以转化为 x≡b(modk) x ≡ b ( m o d k ) 。
最终我们发现这就是一个经典的一次同余方程组。
突然发现嘴上 AC A C 好简单。
那么问题来了, exgcd() e x g c d ( ) 解二元一次不定方程的正整数解花了我 90min 90 m i n ,然后 CRT C R T 我调试学习了一个早上还是没有打出来,本来数据保证了 lcm(Pi)≤1012 l c m ( P i ) ≤ 10 12 ,中国剩余定理合并是一下子的事情,我果然是太菜了。
然后我无奈打了一个优化的暴力枚举解的方法,期望得分 100→? 100 → ? 。
唯一的送分题都被我打挂了。。。
然后就没时间打后两题了。
T2 T 2 本来写个树链剖分可以骗到更多分数的,但是只能写一个连暴力分都拿不满的暴力?
T3 T 3 暴力有 20pts 20 p t s ,但我也来不及写了。
会的东西不要不会用,看过的算法要好好学,不要调用的时候出不来。
数学知识更是应该好好看,数学的话考理解会比背板子更多。
晚上官方公布选手成绩。
本校选手 LargestJN L a r g e s t J N 成功踩线 Au(441 A u ( 441 ,差了 11pts 11 p t s 进集训队,成为本校第一个信息学国赛金牌选手!
发现 BJOI B J O I 的初三队长 Rank7 R a n k 7 ,吓人。
ZJOI Z J O I 初三 A A 队选手Rank54 R a n k 54 ,同样%%%。
听说 Day2 D a y 2 基准分 100+20+20 100 + 20 + 20 ?感觉我只要发挥稳定也能上线被虐。
452=100+100+44+68+100+20+20 452 = 100 + 100 + 44 + 68 + 100 + 20 + 20 感觉基准分打满不失误就能***了?
我发现我最大的问题就是算法会了,题目看不懂(读题速度太慢),做题速度太慢、思考速度太慢。
说白了就是题目做的少。
X=10 X = 10 。
NOI N O I 同步赛还有 19 19 年少 2 2 天出成绩,开心。
今天是一场考试。
我们在这里的最后一场模拟赛。
果然T1 T 1 送分,就是一个 109 10 9 的素因数枚举计数问题。
我手贱打了一个 Pollard−Rho P o l l a r d − R h o (逃)。
T2 T 2 一眼看上去一脸可做的样子。
题意:
给定一个序列求所有的 ∑nl=1∑nr=iMax(Ai)∗xorri=lAi(l≤i≤r) ∑ l = 1 n ∑ r = i n M a x ( A i ) ∗ x o r i = l r A i ( l ≤ i ≤ r ) 的加和。
然后一个惊奇的发现: x x xor x o r y=x+y−2(x y = x + y − 2 ( x and a n d y) y ) 。
先记一趟 Si S i 作为 Ai A i 的前缀 xor x o r 和,然后序列操作转换为单点操作。
这不就好做得很了吗?
∑ni=1∑nj=iAi+Aj ∑ i = 1 n ∑ j = i n A i + A j 显然就是一个计数问题, O(1) O ( 1 ) 出解。
∑ni=1∑nj=iAi ∑ i = 1 n ∑ j = i n A i and a n d Aj A j 显然拆一下二进制就好了,具体的话见下面:
事实上这份代码永远跑不满最坏复杂度,事实上,它的小常数可以完爆 O(n×log2Ai) O ( n × log 2 A i ) 的正解。
但是唯一的问题就是,当值单调的时候,我们可以发现递归的系统栈空间是 O(n) O ( n ) 的, NOIP N O I P 当然没问题,但是不开栈的出题人就会把你卡成暴力分,所以推荐手写栈。
T3 T 3 是一个计数题,理论 40 40 分的暴力实际上能拿 60pts 60 p t s ,正解是线段树维护一下简化后的三维坐标。
所以我的分数(开栈): 100+100+60=260 100 + 100 + 60 = 260 ,如果联赛能够 260+250=510 260 + 250 = 510 ,我就十分满足了。
绍兴一中这边其实集训还没有结束,但是我们还是接了义中的一批人回来了。
在绍兴这边我发现了有许多强校与弱校之间的差距,教学方法上的,还有题目管理方式上的。