T1 队长快跑

本身dp就不强的小马看到这题并未反映过来是个dp(可能是跟题面太过于像那个黑题的队长快跑相似)

总之,基础dp也没搞出来,不过这题倒是启发了小马以后考试要往dp哪里想想

$dp_{i,S}$表示处理到i号水晶,其中选择的要摧毁的水晶A最小为S

正解思路应先考虑出$O(n^3)$的$dp$方程:

$(A_i\leq B_i)dp_{i,A_i}=max(dp_{i-1,B_i+1},dp_{i-1,B_i+2}...dp_{i-1,MAX})+1$

$(A_i>B_i)dp_{i,A_i}=max(dp_{i-1,A_i+1},dp_{i-1,A_i+2}...dp_{i-1,MAX})+1$

$dp_{i,j}=dp_{i-1,j}+1$其中$j\epsilon (B_i,A_i]$

这样的话转移需要$O(n^3)$复杂度

考虑优化

发现$dp$方程可以对应线段树操作,即

单点修改,区间查询等。

 1 #include<bits/stdc++.h>
2 #define int long long
3 #define lid (id<<1)
4 #define rid (id<<1|1)
5 using namespace std;
6 inline int read(){
7 int x=0,f=1; char ch=getchar();
8 while(ch<'0'||ch>'9'){ if(ch=='-') f=-1; ch=getchar(); }
9 while(ch>='0'&&ch<='9'){ x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
10 return x*f;
11 }
12 int n,a[8000000],b[8000000],dis[8000000],cnt,neww;
13 struct SNOWtree{
14 int ll[16000000],rr[16000000];
15 int maxn[16000000],lzy[16000000];
16 inline void pushdown(int id){
17 if(!lzy[id]||ll[id]==rr[id]) return;
18 maxn[lid]+=lzy[id]; maxn[rid]+=lzy[id];
19 lzy[lid]+=lzy[id]; lzy[rid]+=lzy[id];
20 lzy[id]=0;
21 }
22 void build(int id,int l,int r){
23 ll[id]=l; rr[id]=r;
24 if(l==r) return;
25 int mid=(l+r)>>1;
26 build(lid,l,mid);
27 build(rid,mid+1,r);
28 }
29 void update(int id,int l,int r,int v){
30 if(l<=ll[id]&&rr[id]<=r){
31 maxn[id]+=v; lzy[id]+=v;
32 return;
33 }
34 pushdown(id);
35 int mid=(ll[id]+rr[id])>>1;
36 if(l<=mid) update(lid,l,r,v);
37 if(r>mid) update(rid,l,r,v);
38 maxn[id]=max(maxn[lid],maxn[rid]);
39 }
40 void update_sg(int id,int x,int v){
41 if(ll[id]==rr[id]){
42 maxn[id]=max(maxn[id],v);
43 return;
44 }
45 pushdown(id);
46 int mid=(ll[id]+rr[id])>>1;
47 if(x<=mid) update_sg(lid,x,v);
48 else update_sg(rid,x,v);
49 maxn[id]=max(maxn[lid],maxn[rid]);
50 }
51 int query(int id,int l,int r){
52 if(l<=ll[id]&&rr[id]<=r) return maxn[id];
53 pushdown(id);
54 int mid=(ll[id]+rr[id])>>1,ans=0;
55 if(l<=mid) ans=max(ans,query(lid,l,r));
56 if(r>mid) ans=max(ans,query(rid,l,r));
57 return ans;
58 }
59 }tr;
60 namespace WSN{
61 inline int main(){
62 n=read();
63 for(int i=1;i<=n;i++){
64 dis[++cnt]=a[i]=read();
65 dis[++cnt]=b[i]=read();
66 }
67 sort(dis+1,dis+cnt+1);
68 neww=unique(dis+1,dis+cnt+1)-dis-1;
69 for(int i=1;i<=n;i++){
70 a[i]=lower_bound(dis+1,dis+neww+1,a[i])-dis;
71 b[i]=lower_bound(dis+1,dis+neww+1,b[i])-dis;
72 }
73 tr.build(1,1,neww);
74 for(int i=1;i<=n;i++)
75 if(a[i]<=b[i])
76 tr.update_sg(1,a[i],(tr.query(1,b[i]+1,neww)+1));
77 else{
78 tr.update(1,(b[i]+1),a[i],1);
79 tr.update_sg(1,a[i],(tr.query(1,a[i]+1,neww)+1));
80 }
81 printf("%lld\n",tr.maxn[1]);
82 return 0;
83 }
84 }
85 signed main(){return WSN::main();}

T2 影魔

一看这题目,直接傻掉,当时做线段树合并的时候就看到过一道影魔

博主说线段树合并里较难的一个叫队长快跑,一个叫影魔。。。。

然而,题目却并不一样

现在想想,这提应该没有那个难

首先要理解清楚题目让你球的是什么东西(不过估计也只有我把题意理解成加法计算。)

然而他给的灵魂种类都只是一个种类,代表一种人,

最后让统计的是不同的数字有几个,并非加法,而是个数。

那么我们先考虑树链剖分求出距离和LCA,这个比较好想

然后就是超纲知识——主席树(可持久化线段树)。

我们用点的深度为版本开主席树。

先把每个点的深度按从小到大的顺序排序,深度一样的点放进一颗主席树中,具体操作用vector存一下循环便利即可

note:一定注意对应关系!!即vector中插的是dfn序

然后依次查找插入节点的前驱,后继

并分别两两找到其对应的LCA

1.前驱与插入点的LCA-1

2.后继与插入点的LCA-1

3.前驱与后继的LCA+1

注意判断如果前驱或后继是哨兵(inf)那就是没有前/后点,跳过本此操作即可

然后对于每次询问先框定其询问的深度范围,超过最深点的版本默认最深,查找就行。

  1 #include<bits/stdc++.h>
2 #define lid (id<<1)
3 #define rid (id<<1|1)
4 #define lc t[i].ch[0]
5 #define rc t[i].ch[1]
6 #define LC t[j].ch[0]
7 #define RC t[j].ch[1]
8 using namespace std;
9 inline int min(int a,int b){return a<b?a:b;}
10 inline int max(int a,int b){return a>b?a:b;}
11 inline bool cmp(int a,int b){return a<b;}
12 inline void swap(int &a,int &b){a^=b^=a^=b;}
13 inline int read(){
14 int x=0,f=1; char ch=getchar();
15 while(ch<'0'||ch>'9'){ if(ch=='-') f=-1; ch=getchar(); }
16 while(ch>='0'&&ch<='9'){ x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
17 return x*f;
18 }
19 const int NN=8000000,inf=0x7fffffff;
20 vector<int> deep[NN];
21 struct SNOW{int from,to,next;}; SNOW e[NN]; int head[NN],rp;
22 struct hjt{int v,ch[2];}t[NN];
23 struct Splay{int fa,son[2],siz,val;}s[NN];
24 int n,m,c[NN],dep_max,tot;
25 int dfn[NN],rk[NN],son[NN],fa[NN],dep[NN],siz[NN],top[NN],tmp;
26 int cnt,num,rt[NN];
27 inline void add(int x,int y){
28 e[++rp]=(SNOW){x,y,head[x]};head[x]=rp;
29 e[++rp]=(SNOW){y,x,head[y]};head[y]=rp;
30 }
31 inline void dfs1(int f,int x){
32 fa[x]=f; dep[x]=dep[f]+1; siz[x]=1;
33 for(int i=head[x];i;i=e[i].next){
34 int y=e[i].to;
35 if(y==f) continue;
36 dfs1(x,y);
37 siz[x]+=siz[y];
38 if(siz[son[x]]<siz[y]) son[x]=y;
39 }
40 }
41 inline void dfs2(int x,int t){
42 top[x]=t; dfn[x]=++tmp; rk[tmp]=x;
43 if(!son[x]) return;
44 dfs2(son[x],t);
45 for(int i=head[x];i;i=e[i].next){
46 int y=e[i].to;
47 if(y!=fa[x]&&y!=son[x]) dfs2(y,y);
48 }
49 }
50 inline int LCA(int x,int y){
51 while(top[x]!=top[y]){
52 if(dep[top[x]]<dep[top[y]]) swap(x,y);
53 x=fa[top[x]];
54 }
55 if(dfn[x]>dfn[y]) swap(x,y);
56 return x;
57 }
58 void update(int &i,int j,int l,int r,int pos,int val){
59 i=++num; lc=LC; rc=RC; t[i].v=t[j].v;
60 if(l==r){t[i].v+=val;return;}
61 int mid=l+r>>1;
62 if(pos<=mid) update(lc,LC,l,mid,pos,val);
63 else update(rc,RC,mid+1,r,pos,val);
64 t[i].v=t[lc].v+t[rc].v;
65 }
66 int query(int i,int l,int r,int L,int R){
67 if(!i||L>R) return 0;
68 if(l==L&&R==r) return t[i].v;
69 int mid=l+r>>1;
70 if(R<=mid) return query(lc,l,mid,L,R);
71 if(L>mid) return query(rc,mid+1,r,L,R);
72 return query(lc,l,mid,L,mid)+query(rc,mid+1,r,mid+1,R);
73 }
74 struct SPLAY{
75 int root;
76 void pushup(int x){
77 s[x].siz=s[s[x].son[0]].siz+s[s[x].son[1]].siz+1;
78 }
79 int get(int x){
80 return x==s[s[x].fa].son[1];
81 }
82 void rotate(int x){
83 int y=s[x].fa,z=s[y].fa,xpos=get(x),ypos=get(y);
84 s[z].son[ypos]=x; s[x].fa=z;
85 s[y].son[xpos]=s[x].son[xpos^1]; s[s[x].son[xpos^1]].fa=y;
86 s[x].son[xpos^1]=y; s[y].fa=x;
87 pushup(y); pushup(x);
88 }
89 void splay(int x,int goal){
90 while(s[x].fa!=goal){
91 int y=s[x].fa,z=s[y].fa,xpos=get(x),ypos=get(y);
92 if(z!=goal){
93 if(xpos==ypos) rotate(y);
94 else rotate(x);
95 }
96 rotate(x);
97 }
98 if(!goal) root=x;
99 }
100 void insert(int val){
101 int u=root,ff=0;
102 while(u&&s[u].val!=val)
103 ff=u,u=s[u].son[val>s[u].val];
104 u=++tot;
105 if(ff) s[ff].son[val>s[ff].val]=u;
106 s[u].son[0]=s[u].son[1]=0;
107 s[u].fa=ff;s[u].val=val;
108 s[u].siz=1;
109 splay(u,0);
110 }
111 void find_rank(int val){
112 int u=root;
113 if(!u) return;
114 while(s[u].son[val>s[u].val] && val!=s[u].val) u=s[u].son[val>s[u].val];
115 splay(u,0);
116 }
117 int prenxt(int val,int op){
118 find_rank(val);
119 int u=root;
120 if(s[u].val>val && op) return s[u].val;
121 if(s[u].val<val &&!op) return s[u].val;
122 u=s[u].son[op];
123 while(s[u].son[op^1]) u=s[u].son[op^1];
124 return s[u].val;
125 }
126 };SPLAY que[NN];
127 namespace WSN{
128 inline int main(){
129 // FILE *A=freopen("1.in","r",stdin);
130 // FILE *B=freopen("1.out","w",stdout);
131 n=read();m=read();
132 for(int i=1;i<=n;i++){
133 c[i]=read();
134 que[c[i]].insert(-inf);
135 que[c[i]].insert(inf);
136 }
137 for(int i=1;i<n;i++){int fa=read(); add(fa,i+1);}
138 dfs1(0,1); dfs2(1,1);
139 for(int i=1;i<=n;i++){
140 deep[dep[i]].push_back(dfn[i]);
141 dep_max=max(dep_max,dep[i]);
142 }
143 for(int i=1;i<=dep_max;i++){
144 for(int j=0;j<deep[i].size();j++){
145 int p=!j?i-1:i;
146 int node=deep[i][j],pre,nxt,color=c[rk[node]];
147 que[color].insert(node);
148 pre=que[color].prenxt(node,0);
149 nxt=que[color].prenxt(node,1);
150 update(rt[i],rt[p],1,n,node,1);
151 if(pre!=inf&&pre!=-inf){
152 int lca=LCA(rk[pre],rk[node]);
153 update(rt[i],rt[i],1,n,dfn[lca],-1);
154 }
155 if(nxt!=inf&&nxt!=-inf){
156 int lca=LCA(rk[nxt],rk[node]);
157 update(rt[i],rt[i],1,n,dfn[lca],-1);
158 }
159 if(pre!=inf&&pre!=-inf&&nxt!=inf&&nxt!=-inf){
160 int lca=LCA(rk[pre],rk[nxt]);
161 update(rt[i],rt[i],1,n,dfn[lca],1);
162 }
163 }
164 }
165 while(m--){
166 int U=read(),D=read();
167 int range=min(dep[U]+D,dep_max);
168 int ans=query(rt[range],1,n,dfn[U],dfn[U]+siz[U]-1);
169 printf("%d\n",ans);
170 }
171 return 0;
172 }
173 }
174 signed main(){return WSN::main();}

至于查找前驱后继之类的操作可以用set比较方便,但是看一旁的zxs和JYFHYX同学磕指针很费劲的样子,于是便悄咪咪的打了splay,4.4K代码超爽

T3 抛硬币

又一个dp题,然而这次集训一次没接触导致啥也想不出来好吧。。

艾,小马的dp还是太弱了

看题发现dp可以$O(S^2)$跑,非常舒服

设$f_{i,j}$表示处理完S的前i个位置,长度为j的本质不同子序列个数

如果尾部添加一个字符,最先想到$f_{i,j}=f_{i-1,j}+f_{i-1,j-1}$

然后减去这样会算重的个数

发现算重的部分一定是结尾为$S_i$的串

则假设$S_i$上一次出现的位置为p,那么算重的串个数即为$f_{p-1,j-1}$

那么直接$n^2$转移即可。

 1 #include<bits/stdc++.h>
2 #define int long long
3 using namespace std;
4 inline int read(){
5 int x=0,f=1; char ch=getchar();
6 while(ch<'0'||ch>'9'){ if(ch=='-') f=-1; ch=getchar(); }
7 while(ch>='0'&&ch<='9'){ x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
8 return x*f;
9 }
10 const int NN=5005,p=998244353;
11 int l,pre[NN],vis[30],f[NN][NN];
12 char s[NN];
13 namespace WSN{
14 inline int main(){
15 scanf("%s",s+1); l=read();
16 int n=strlen(s+1);
17 for(int i=1;i<=n;i++){
18 int ch=s[i]-'a';
19 if(!vis[ch]){
20 vis[ch]=i;
21 }
22 else{
23 pre[i]=vis[ch];
24 vis[ch]=i;
25 }
26 }
27 for(int i=0;i<=n;i++) f[i][0]=1;
28 for(int i=1;i<=n;i++)
29 for(int j=1;j<=l;j++)
30 if(!pre[i]) f[i][j]=(f[i-1][j]+f[i-1][j-1])%p;
31 else f[i][j]=(f[i-1][j]+f[i-1][j-1]-f[pre[i]-1][j-1]+p)%p;
32 printf("%lld\n",f[n][l]);
33 return 0;
34 }
35 }
36 signed main(){return WSN::main();}

Noip模拟14 2021.7.13的更多相关文章

  1. Noip模拟52 2021.9.13

    T1 异或 比较稳的切掉 观察数据范围,无法线性筛啥的,根号复杂度也会死,于是只能考虑$log$级 然后打表 发现当$n$为$2^i$时的答案是一个可递归数列: $1,3,7,15,31,63,127 ...

  2. Noip模拟38 2021.8.13

    T1 a 跟入阵曲很像,但是忘记入阵曲这题的思路是什么了 这里再提一下,入阵曲是子矩阵和是$k$的倍数,这道题目是子矩阵和是在一段区间内$[L,R]$ 因为这道题$n$特别小,$m$较大,考虑复杂度为 ...

  3. Noip模拟76 2021.10.14

    T1 洛希极限 上来一道大数据结构或者单调队列优化$dp$ 真就没分析出来正解复杂度 正解复杂度$O(q+nm)$,但是据说我的复杂度是假的 考虑一个点转移最优情况是从它上面的一个反$L$形转移过来 ...

  4. Noip模拟53 2021.9.14

    T1 ZYB和售货机 首先这道题有两种做法. 一种是发现每个点都可以先被取到只剩一个,只要收益大于$0$ 然后发现建一个$i->f[i]$的图时出现环,要把它去掉, 那么跑一个$tarjan$枚 ...

  5. Noip模拟39 2021.8.14

    T1 打地鼠 都切掉了的简单题 1 #include<bits/stdc++.h> 2 #define int long long 3 using namespace std; 4 con ...

  6. Noip模拟15 2021.7.14

    T1 夜莺与玫瑰 题目越发的变态起来... 这题刚开始看超级像仪仗队,好不容易码完欧拉函数后尝试×2后输出但不对!! 于是选择了跳过.... 正解居然是莫比乌斯函数....我也是醉了 预处理完就剩下$ ...

  7. Noip模拟70 2021.10.6

    T1 暴雨 放在第一道的神仙题,不同的做法,吊人有的都在用线段树维护$set$预处理 我是直接$dp$的,可能代码的复杂度比那种的稍微小一点 设$f[i][j][p][0/1]$表示考虑了前$i$列, ...

  8. Noip模拟69 2021.10.5

    考场拼命$yy$高精度结果没学好$for$循环痛失$50pts$,当场枯死 以后一定打对拍,要不考后会... T1 石子游戏 首先要知道典型的$NIM$博弈,就是说如果所有堆石子个数的异或和为$0$则 ...

  9. Noip模拟63 2021.9.27(考场惊现无限之环)

    T1 电压机制 把题目转化为找那些边只被奇数环包含. 这样的话直接$dfs$生成一棵树,给每个点附上一个深度,根据其他的非树边都是返祖边 可以算出环内边的数量$dep[x]-dep[y]+1$,然后判 ...

随机推荐

  1. CommonsCollections3 反序列化利用链分析

    InstantiateTransformer commons-collections 3.1 中有 InstantiateTransformer 这么一个类,这个类也实现了 Transformer的t ...

  2. idea鼠标双击.log日志文件无法打开

    发现只要再mybatis-config.xml的起别名中加<package name="xxx"/>,就会导致Reader entry: ����   1 n乱码,而R ...

  3. 什么是云效 Projex,云效Projex企业级高效研发项目管理平台

    云效项目协作Projects是一款企业级高效研发项目管理平台, 提供了快速实践的敏捷研发项目管理机制,提供对需求.迭代.缺陷各个维度的协同管理以及相关的统计报告,让研发团队高效协作.践行敏捷并持续交付 ...

  4. Java面向对象系列(2)- 回顾方法的定义

    方法的定义 修饰符 返回类型 break:跳出switch,结束循环和return的区别 方法名:注意规范,见名知意 参数列表:(参数类型,参数名) 异常抛出 package oop.demo01; ...

  5. 使用form插件 和ajax 结合使用 没有调用success的原因

    当我做文件上传的时候出现不调用success方法  将datype: 'json' 注释掉后成功响应 浏览器显示200状态码,并且响应头为json格式,格式ajax不认为它是json,所以一直执行错误 ...

  6. Centos7创建swap分区

    创建4g swap分区 dd if=/dev/zero of=/var/swap bs=1024 count=4194304 mkswap /var/swap 激活swap分区 swapon /var ...

  7. 低差异序列 (low-discrepancy sequences)之Hammerysley在半球中采样点方法的介绍

    半球上的Hammersley 源作者:Holger Dammertz 一组关于如何在2D中使用Hammersley点集以在着色器程序中快速实用地生成半球方向的笔记.如果你发现任何错误或有意见,不要犹豫 ...

  8. CF990G-GCD Counting【dfs】

    正题 题目链接:https://www.luogu.com.cn/problem/CF990G 题目大意 给出一棵有点权的树,对于每个\(k\)求有多条路径的点权\(gcd\)为\(k\) \(1\l ...

  9. 什么鬼?你还搞不懂json和字典的区别??

    现在自动化培训烂大街,是个人都能说的上几个框架,面试如果问框架相关问题,求职者只需一瓶 82 年的雪碧,会吹的让你怀疑人生!所以面试官为了更清楚的知道你是停留在表面上的花拳绣腿还是有扎实的基础,就不会 ...

  10. FastAPI小项目实战:电影列表(Vue3 + FastAPI)

    假期过半, FastAPI + Vue3项目实战 视频也算录完了,尽管项目简单(2张表 共7个接口 4个页面) 起因 在6月底的时候开始录制了FastAPI官方文档中的新手教程部分(实际还没有官网文档 ...