T1 string(线段树优化)

看到数据范围就必须要想到优化,那么如何把26×M∗N 的复杂度降低呢??

用到那个我们最不想打的数据结构——线段树。。。。。。

然而,这个线段树与往常不同,他只需要用lazy下标,这样的话,也会比往常的码量稍微小点

(听别人说,这提可能还需要卡常)

不说了,代码表示比较明白

 

 1 #include<bits/stdc++.h>
2 #define lid (id<<1)
3 #define rid (id<<1|1)
4 using namespace std;
5 inline int read(){
6 int x=0,f=1; char ch=getchar();
7 while(ch<'0'||ch>'9'){ if(ch=='-') f=-1; ch=getchar(); }
8 while(ch>='0'&&ch<='9'){ x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
9 return x*f;
10 }
11 int n,m,summ[27];char s[100005];
12 struct tree{
13 int l,r,sum,lazy;
14 }; tree t[100005<<2];
15 inline void pushup(int id){
16 if(t[lid].sum==t[rid].sum) t[id].sum=t[lid].sum;
17 else t[id].sum=-1;
18 }
19
20 inline void pushdown(int id){
21 if(t[id].sum!=-1) t[lid].sum=t[rid].sum=t[id].sum;
22 }
23
24 inline void bt(int id,int l,int r){
25 t[id].l=l; t[id].r=r; t[id].sum=-1;
26 if(l==r){ t[id].sum=s[l]-'a'; return; }
27 int mid=(l+r)>>1;
28 bt(lid,l,mid);
29 bt(rid,mid+1,r);
30 pushup(id);
31 }
32
33 inline void add(int id,int l,int r){
34 if(t[id].l>=l&&t[id].r<=r){
35 if(t[id].sum!=-1){
36 summ[t[id].sum]+=t[id].r-t[id].l+1;
37 return;
38 }
39 }
40 pushdown(id);
41 int mid=(t[id].l+t[id].r)>>1;
42 if(l<=mid) add(lid,l,r);
43 if(mid+1<=r) add(rid,l,r);
44 }
45
46 inline void change(int id,int l,int r,int v){
47 if(l>r) return;
48 if(t[id].l>=l&&t[id].r<=r){ t[id].sum=v; return;}
49 int mid=(t[id].l+t[id].r)>>1;
50 if(l<=mid) change(lid,l,r,v);
51 if(mid+1<=r) change(rid,l,r,v);
52 pushup(id);
53 }
54
55 inline void qu(int id){
56 if(t[id].sum!=-1){
57 for(int i=1;i<=t[id].r-t[id].l+1;i++)
58 putchar(t[id].sum+'a');
59 return;
60 }
61 qu(lid);
62 qu(rid);
63 }
64 namespace WSN{
65 inline int main(){
66 n=read(),m=read();
67 scanf("%s",s+1);
68 bt(1,1,n);
69 while(m--){
70 memset(summ,0,sizeof(summ));
71 int l=read(),r=read(),x=read();
72 add(1,l,r);
73 if(x==1){
74 int ll=l;
75 for(int i=0;i<=25;i++){
76 change(1,ll,ll+summ[i]-1,i);
77 ll+=summ[i];
78 }
79 }
80 if(x==0){
81 int ll=l;
82 for(int i=25;i>=0;i--){
83 change(1,ll,ll+summ[i]-1,i);
84 ll+=summ[i];
85 }
86 }
87 }
88 qu(1);
89 return 0;
90 }
91 }
92 signed main(){return WSN::main();}

T2 Matrix(Dp)

首先说一下,当这个题我看到dp方程表示的含义时,就吐了。。。这什么鬼才想出来的??? %%cbx

dp[i][j]表示在扫描到第i列时右区间的左端点在第i列左侧的个数是j,数组反映方案数。

唉,这大长定语我身为语文弱者已经尽力了。。。

数组l,r分别表示左区间的右端点在1~l间的个数:右区间的左端点在1~r间的个数,相当于维护一个前缀和

先考虑左区间:

扫描过一列后,扫面下一列而l[i]==l[i-1],表示该列无新的扫描完的左区间: f[i][j]=f[i1-][j]

扫描过一列后,扫面下一列而l[i]!=l[i-1],表示该列有新的扫描完的左区间:

 总共有 l[i]−l[i−1]个左区间需要安排 1 ,之前还空着的列有 i−j−l[i−1] 个,所以安排左区间的方案数为

    $P^{l[i]-l[i-1]}_{i-j-l[i-1]}$

再考虑右区间:

j>0,则f[i][j]可以由f[i-1][j-1]转移而来。总共r[i]行,放了j-1行,还剩r[i]-(j-1)行:

    $f [ i ][ j ]+=f [ i - 1 ][ j-1 ]*[r[i]-(j-1)]*P^{l[i]-l[i-1]}_{i-j-l[i-1]}$

 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=3002,p=998244353;
11 int n,m,l[NN],r[NN],f[NN][NN];
12 namespace WSN{
13 inline int main(){
14 f[0][0]=1;
15 n=read(),m=read();
16 for(int i=1;i<=n;i++){
17 int L=read(),R=read();
18 l[L]++,r[R]++;
19 }
20 for(int i=1;i<=m;i++){
21 f[i][0]=f[i-1][0];
22 l[i]+=l[i-1];
23 r[i]+=r[i-1];
24 for(int j=1;j<=i;j++)
25 f[i][j]=(f[i-1][j]+f[i-1][j-1]*(r[i]-(j-1))%p)%p;
26 for(int k=0;k<=i;k++)
27 for(int j=l[i-1];j<l[i];j++)
28 f[i][k]=f[i][k]*(i-j-k)%p;
29 }
30 printf("%lld\n",f[m][n]);
31 return 0;
32 }
33 }
34 signed main(){return WSN::main();}

T3 Big (trie树)

巧妙的将复杂的函数取模柿子转化为理解的懂得柿子:

前面的地板函数模完2^n后值域是0和1,后面加上2x并模一个2^n意思是向左移一位加起来就是相当于将原数的二进制首位推到末尾,其他位向前移动一位,举个不是二进制的例子

1234----->> 2341

这样,我们就可以明显的发现这是一道trie树题

我们以对手的操作为断点,前面会让x xor一些数,操作后也会xor,这样,我们可以记录前缀和,枚举对手操作的各种断点,这样就可以找到最优解了

再提一下的就是分情况

一节点有两个孩子,那么无论我们如何构造x,对手一定能将这一位变为0,所以答案这一位为0

 如果只有一个儿子,那么我们一定可以构造出一个x,使答案的这一位为1,所以答案这一位为1。

所以一边记录最大值一边统计个数就完了

 1 #include<bits/stdc++.h>
2 #define X ((x>>(i-1))&1)
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=300005;
11 int n,m,ch[8000000][3],tot=1,a[NN],s[NN],ans1,ans2;
12 inline int change(int x){return (x>>(n-1))+((x&(~(1<<(n-1))))<<1);}
13 //attacker use problem idea to change the number
14 inline void insert(int x){
15 int u=1;
16 for(int i=n;i>=1;i--){
17 if(!ch[u][X]) ch[u][X]=++tot;
18 u=ch[u][X];
19 }
20 }
21 inline void dfs(int u,int x,int len){
22 if(len==0){
23 if(x>ans1){
24 ans1=x;
25 ans2=1;
26 }else if(x==ans1) ans2++;
27 return;
28 }
29 if(ch[u][0]&&ch[u][1]){
30 dfs(ch[u][0],x,len-1);
31 dfs(ch[u][1],x,len-1);
32 }
33 if(ch[u][0]&&!ch[u][1]) dfs(ch[u][0],(x|(1<<(len-1))),len-1);
34 if(ch[u][1]&&!ch[u][0]) dfs(ch[u][1],(x|(1<<(len-1))),len-1);
35 }
36 namespace WSN{
37 inline int main(){
38 n=read(),m=read();//n mean the length of "2 jinzhi"
39 for(int i=1;i<=m;i++) a[i]=read();
40 for(int i=1;i<=m;i++) s[i]=s[i-1]^a[i];//xor "qian z s[m]^s[i]));
41 for(int i=0;i<=m;i++) insert(change(s[i])^(s[m]^s[i]));
42 dfs(1,0,n);
43 printf("%d\n%d\n",ans1,ans2);
44 return 0;
45 }
46 }
47 signed main(){return WSN::main();}

END

这次考试还是有小问题,就是时间分配不均。

超级有自信的打过了T4,然而也花费了超级多的时间,结果是T4没有拿到满分,前面题也顾不上做,幸好前面的题整体得分不高,而我的第四题想的也是正解思路,总之不亏吧~~

再%%XIN考试全场首A第四题太强了

Noip模拟5 2021.6.7的更多相关文章

  1. Noip模拟70 2021.10.6

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

  2. Noip模拟76 2021.10.14

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

  3. Noip模拟69 2021.10.5

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

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

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

  5. Noip模拟61 2021.9.25

    T1 交通 考场上想了一个$NPC$.应该吧,是要求出图里面的所有可行的不重复欧拉路 无数种做法都无法解出,时间也都耗在这个上面的,于是就考的挺惨的 以后要是觉得当前思路不可做,就试着换一换思路,千万 ...

  6. Noip模拟59 2021.9.22

    新机房首模拟变倒数 T1 柱状图 关于每一个点可以做出两条斜率分别为$1,-1$的直线, 然后题意转化为移动最少的步数使得所有点都在某一个点的两条直线上 二分出直线的高度,判断条件是尽量让这条直线上部 ...

  7. Noip模拟52 2021.9.13

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

  8. Noip模拟51 2021.9.12

    T1 茅山道术 考场上卡在了一个恶心的地方, 当时以为每次施法都会产生新的可以施法的区间,然后想都没细想, 认为不可做,甚至$dfs$也无法打,考后一问发现是自己想多了.. 新产生的区间对答案根本没有 ...

  9. Noip模拟50 2021.9.10

    已经好长时间没有考试不挂分的良好体验了... T1 第零题 开场数据结构,真爽 对于这道题首先要理解对于一条链从上向下和从下向上走复活次数相等 (这可能需要晚上躺在被窝里面脑摸几种情况的样例) 然后就 ...

  10. Noip模拟49 2021.9.7

    T1 reverse 又一道板子打假的挂分题,直接挂到倒二.. 考场上思路神奇,居然想到用$bfs$建边然后跑最短路, 其实当时也想到了直接$bfs$,但是不知道为啥觉得$dij$屌就没直接打$bfs ...

随机推荐

  1. [第十五篇]——Swarm 集群管理之Spring Cloud直播商城 b2b2c电子商务技术总结

    Swarm 集群管理 简介 Docker Swarm 是 Docker 的集群管理工具.它将 Docker 主机池转变为单个虚拟 Docker 主机. Docker Swarm 提供了标准的 Dock ...

  2. go实现堆排序、快速排序、桶排序算法

    一. 堆排序 堆排序是利用堆这种数据结构而设计的一种排序算法.以大堆为例利用堆顶记录的是最大关键字这一特性,每一轮取堆顶元素放入有序区,就类似选择排序每一轮选择一个最大值放入有序区,可以把堆排序看成是 ...

  3. apache php RabbitMQ配置方式

    确定自己的php版本号和位数,去pecl.php.net下载版本相应的rabbitmq扩展包, 以php5版本为例,在http://pecl.php.net/package/amqp里面选择php5对 ...

  4. php 的一些问题

    ------------------------------------------------------------------------------ * 绝对路径转化为相对路径 <?ph ...

  5. php 常用算法与函数

    1.一群猴子排成一圈,按1,2,-,n依次编号.然后从第1只开始数,数到第m只,把它踢出圈,从它后面再开始数,再数到第m只,在把它踢出去-,如此不停的进行下去,直到最后只剩下一只猴子为止,那只猴子就叫 ...

  6. 51nod1836-战忽局的手段【期望dp,矩阵乘法】

    正题 题目连接:http://www.51nod.com/Challenge/Problem.html#problemId=1836 题目大意 \(n\)个点\(m\)次随机选择一个点标记(可以重复) ...

  7. P4831-Scarlet loves WenHuaKe【组合数学】

    正题 题目链接:https://www.luogu.com.cn/problem/P4831 题目大意 \(n*m\)的网格上放置\(2n\)个炮,要求互不能攻击. 数据满足\(n\leq m\leq ...

  8. selenium--常用判断

    获取页面 title 的方法可以直接用 driver.title 获取到,然后也可以把获取到的结果用做断言.1.首先导入 expected_conditions 模块:from selenium.we ...

  9. Anaconda和canda简介及区别

    Anaconda简介: 1.是一个开源的Python发行版本,其包含了conda.Python等软件包,numpy,pandas(数据分析),scipy等科学计算包,而无需再单独下载配置. 可以在同一 ...

  10. CSS 小技巧 | 一行代码实现头像与国旗的融合

    到国庆了,大家都急着给祖国母亲庆生. 每年每到此时,微信朋友圈就会流行起给头像装饰上国旗,而今年又流行这款: emm,很不错. 那么,将一张国旗图片与我们的头像,快速得到想要的头像,使用 CSS 如何 ...