Noip模拟14 2021.7.13
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的更多相关文章
- Noip模拟52 2021.9.13
T1 异或 比较稳的切掉 观察数据范围,无法线性筛啥的,根号复杂度也会死,于是只能考虑$log$级 然后打表 发现当$n$为$2^i$时的答案是一个可递归数列: $1,3,7,15,31,63,127 ...
- Noip模拟38 2021.8.13
T1 a 跟入阵曲很像,但是忘记入阵曲这题的思路是什么了 这里再提一下,入阵曲是子矩阵和是$k$的倍数,这道题目是子矩阵和是在一段区间内$[L,R]$ 因为这道题$n$特别小,$m$较大,考虑复杂度为 ...
- Noip模拟76 2021.10.14
T1 洛希极限 上来一道大数据结构或者单调队列优化$dp$ 真就没分析出来正解复杂度 正解复杂度$O(q+nm)$,但是据说我的复杂度是假的 考虑一个点转移最优情况是从它上面的一个反$L$形转移过来 ...
- Noip模拟53 2021.9.14
T1 ZYB和售货机 首先这道题有两种做法. 一种是发现每个点都可以先被取到只剩一个,只要收益大于$0$ 然后发现建一个$i->f[i]$的图时出现环,要把它去掉, 那么跑一个$tarjan$枚 ...
- Noip模拟39 2021.8.14
T1 打地鼠 都切掉了的简单题 1 #include<bits/stdc++.h> 2 #define int long long 3 using namespace std; 4 con ...
- Noip模拟15 2021.7.14
T1 夜莺与玫瑰 题目越发的变态起来... 这题刚开始看超级像仪仗队,好不容易码完欧拉函数后尝试×2后输出但不对!! 于是选择了跳过.... 正解居然是莫比乌斯函数....我也是醉了 预处理完就剩下$ ...
- Noip模拟70 2021.10.6
T1 暴雨 放在第一道的神仙题,不同的做法,吊人有的都在用线段树维护$set$预处理 我是直接$dp$的,可能代码的复杂度比那种的稍微小一点 设$f[i][j][p][0/1]$表示考虑了前$i$列, ...
- Noip模拟69 2021.10.5
考场拼命$yy$高精度结果没学好$for$循环痛失$50pts$,当场枯死 以后一定打对拍,要不考后会... T1 石子游戏 首先要知道典型的$NIM$博弈,就是说如果所有堆石子个数的异或和为$0$则 ...
- Noip模拟63 2021.9.27(考场惊现无限之环)
T1 电压机制 把题目转化为找那些边只被奇数环包含. 这样的话直接$dfs$生成一棵树,给每个点附上一个深度,根据其他的非树边都是返祖边 可以算出环内边的数量$dep[x]-dep[y]+1$,然后判 ...
随机推荐
- 简说yuv
最近弄了一个读取y4m文件转成yuv的流的事情,记录一些yuv相关的细节 为什么会有yuv 因为我们目前的显示器显示的原理都是三原色,几乎所有的视频数据最后都要转为rgb格式才能渲染到显示屏上,而原始 ...
- 处理器核、Core、处理器、CPU区别&&指令集架构与微架构的区别&&32位与64位指令集架构说明
1.处理器核.Core.处理器.CPU的区别 严格来说"处理器核"和" Core "是指处理器内部最核心的部分,是真正的处理器内核:而"处理器&quo ...
- RSA及其证明 [原创]
描述RSA的实现步骤介绍文章非常多,但说明并证明其原理,并进而讨论为什么这样设计的文章不多.本人才疏学浅,不敢说理解了R.S.A.三位泰斗的设计初衷,简单就自己的理解写一写,博大家一笑. 以下原创内容 ...
- 利用nginx 来实现内网yum源(反向代理)
简介 在项目部署时,尤其是在政府企业,对于外网简直是奢望,但是对于运维来说,没有外网的话只能自建yum源.我今天来说的是一种简单的自建yum源方法,前提是必须有一台内外网都有的机器,我们一般称为前置机 ...
- 分布式搜索引擎Elasticsearch在CentOS7中的安装
1. 概述 随着企业业务量的不断增大,业务数据随之增加,传统的基于关系型数据库的搜索已经不能满足需要. 在关系型数据库中搜索,只能支持简单的关键字搜索,做不到分词和统计的功能,而且当单表数据量到达上百 ...
- TS基础笔记
TS优势 更好的错误的提示,开发中及时发现问题:编辑器语法提示更完善:类型声明可以看出数据结构的语义,可读性更好; TS环境搭建 1.安装node;2.npm install typescript@3 ...
- IDL读取fits文件
使用mrdfits函数 这是天文学标准库中的函数,下载地址:https://idlastro.gsfc.nasa.gov/homepage.html,下载后,将pro文件夹导入到IDL工程中. str ...
- php stream 流封装协议
http://php.net/manual/wrappers.php 过程: 1. 开始通信 2. 读取数据 3. 写入数据 4. 结束通信 usage: * 读写文件系统 <?php $han ...
- php 扫描url死链接
* 从Packagist上搜索需要的包 https://packagist.org/ * 通过composer下载依赖包 composer require guzzlehttp/guzzle comp ...
- java基础面试题(一)
1.java中的数据类型,各占多少个字节? 2.面向对象的特性 1-封装:简单来说,封装就是把数据和操作数据的方法绑定起来,如果需要访问,可以使用已定义的接口进行访问 2-继承:从已有的类得到继承信息 ...