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. Kubernetes-Pod介绍(二)-生命周期

    前言 本篇是Kubernetes第五篇,大家一定要把环境搭建起来,看是解决不了问题的,必须实战. Kubernetes系列文章: Kubernetes介绍 Kubernetes环境搭建 Kuberne ...

  2. CentOS8部署tftp

    tftp:简单文本传输协议,而ftp:文本传输协议.可以把tftp看成是ftp的精简版.tftp用于免登录传输小文件,tftp服务端监听在udp协议的69端口tftp简单的工作原理: tftp服务端与 ...

  3. Sentry 监控 - Security Policy 安全策略报告

    系列 1 分钟快速使用 Docker 上手最新版 Sentry-CLI - 创建版本 快速使用 Docker 上手 Sentry-CLI - 30 秒上手 Source Maps Sentry For ...

  4. Writing in the Science 01

    INTRODUCTION What makes good writing? Good writing communicates an idea clearly and effectively. Goo ...

  5. Django边学边记—模型查询

    查询集 两大特性 惰性执行:创建查询集不会访问数据库,直到调用数据时,才会访问数据库,调用数据的情况包括迭代.序列化.与if合用 缓存:查询集的结果被存下来之后,再次查询时会使用之前缓存的数据 返回列 ...

  6. TP框架中的一些登录代码分享

    <?php namespace Admin\Controller;use Think\Controller;class LoginController extends Controller{ p ...

  7. 『PyTorch』矩阵乘法总结

    1. 二维矩阵乘法 torch.mm() torch.mm(mat1, mat2, out=None),其中mat1(\(n\times m\)),mat2(\(m\times d\)),输出out的 ...

  8. 完美解决JavaIO流报错 java.io.FileNotFoundException: F:\ (系统找不到指定的路径。)

    完美解决JavaIO流报错 java.io.FileNotFoundException: F:\ (系统找不到指定的路径.) 错误原因 读出文件的路径需要有被拷贝的文件名,否则无法解析地址 源代码(用 ...

  9. P5488-差分与前缀和【NTT,生成函数】

    正题 题目链接:https://www.luogu.com.cn/problem/P5488 题目大意 求一个长度为$n$的序列的$k$阶差分/前缀和. 解题思路 先考虑前缀和怎么做 搞出来生成函数就 ...

  10. P4357-[CQOI2016]K远点对【K-Dtree】

    正题 题目链接:https://www.luogu.com.cn/problem/P4357 题目大意 平面上给出\(n\)个点,求第\(k\)远的点对距离. 解题思路 \(\text{K-Dtree ...