模拟11题解

T1[A. string]「桶排序」「线段树」

线段树维护区间的每个字母出现了多少次,

在排序的时候,先查询一个区间的每个字母的出现次数,然后挨个区间赋值

复杂度  $O(mlog(n)*26)$

优化常数(26):定义f(懒标记):f!=0时,代表子树都被赋值为了同一个值;f==0,表示不相等。

将区间查询改为只有访问到了f!=0再对ans贡献return,pushup,pushdown同理,避免了枚举26

当然也可以循环展开勉强卡过

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #define mid ((t[k].l+t[k].r)>>1)
  6 #define lc (k<<1)
  7 #define rc (k<<1|1)
  8 #define R register
  9 using namespace std;
 10 int read()
 11 {
 12     int f=1,x=0;char ch=getchar();
 13     while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)f=-1;ch=getchar();}
 14     while(ch<=‘9‘&&ch>=‘0‘){x=(x<<3)+(x<<1)+ch-‘0‘;ch=getchar();}
 15     return f*x;
 16 }
 17 const int maxn=100005;
 18 struct node{
 19     int l,r,sum,f;
 20 }t[maxn*4];
 21 char s[maxn];
 22 int a[maxn],ans[30];
 23 inline void up(R int k)
 24 {
 25     if(t[lc].f==t[rc].f&&t[lc].f)  t[k].f=t[lc].f;
 26     else t[k].f=0;
 27 }
 28 inline void down(R int k)
 29 {
 30     t[lc].f=t[rc].f=t[k].f;
 31 }
 32 void build(R int k,R int l,R int r)
 33 {
 34     t[k].l=l,t[k].r=r;
 35     if(l==r)
 36     {
 37         t[k].f=a[l];
 38         t[k].sum=1;
 39         return;
 40     }
 41     build(lc,l,mid);
 42     build(rc,mid+1,r);
 43     t[k].sum=t[lc].sum+t[rc].sum;
 44     up(k);
 45 }
 46 void query(R int k,R int l,R int r)
 47 {
 48     if(t[k].l>=l&&t[k].r<=r&&t[k].f)
 49     {
 50         ans[t[k].f]+=t[k].sum;
 51         return;
 52     }
 53     if(t[k].f)down(k);
 54     if(l<=mid)query(lc,l,r);
 55     if(r>mid)query(rc,l,r);
 56     up(k);
 57 }
 58 void change(R int k,R int l,R int r,R int w)
 59 {
 60     if(t[k].l>=l&&t[k].r<=r)
 61     {
 62         t[k].f=w;
 63         return;
 64     }
 65     if(t[k].f) down(k);
 66     if(l<=mid)change(lc,l,r,w);
 67     if(r>mid)change(rc,l,r,w);
 68     up(k);
 69 }
 70 void print(R int k)
 71 {
 72     if(t[k].l==t[k].r)
 73     {
 74         char ch=t[k].f+‘a‘-1;
 75         printf("%c",ch);
 76         return;
 77        }
 78     if(t[k].f)  down(k);
 79     print(lc);
 80     print(rc);
 81 }
 82 int main()
 83 {
 84  //  freopen("data","r",stdin);
 85     const int n=read(),m=read();
 86     scanf("%s",s+1);
 87     for(R int i=1;i<=n;++i)
 88         a[i]=s[i]-‘a‘+1;
 89     build(1,1,n);
 90     for(R int i=1;i<=m;++i)
 91     {
 92         R int l=read(),r=read(),x=read();
 93         memset(ans,0,sizeof ans);
 94         query(1,l,r);
 95         if(x)
 96         {
 97             for(R int i=1;i<=26;++i)
 98                 if(ans[i])
 99                 {
100                     change(1,l,l+ans[i]-1,i);
101                     l=l+ans[i];
102                 }
103         }
104         else
105         {
106             for(R int i=26;i>=1;--i)
107                 if(ans[i])
108                 {
109                     change(1,l,l+ans[i]-1,i);
110                     l=l+ans[i];
111                 }
112         }
113     }
114     print(1);
115 }
116 /*
117 g++ 1.cpp -o 1
118 ./1
119
120 */

T2 [B. matrix]「动态规划--两没一毒」

定义f[i][j]:从左向右到了第i列(也就是有了i个1能放),有j个一放在了右区间,

l[i]:到i列为止,有多少行的左区间已经结束;   r[i]:到i列为止,有多少右区间已经开始;

f[i][j]=f[i-1][j]+f[i-1][j-1]*(r[i]-(j-1));

  前者为不放,后者 是再多放一个,j-1是右区间已经放了j-1个,总共有r[i]个空

f[i][j]要乘上:A(i-j-l[i-1],l[i]-l[i-1])

  l[i]-l[i-1]是第i列的能放的空,i是总共能有的1的个数,j个放在了右区间,l[i-1]个一定要放在已经结束的i-1个左区间里,剩下的选出来去放在能放的空里

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #define int long long
 6 using namespace std;
 7 const int maxn=3005;
 8 const int mod=998244353 ;
 9 int read()
10 {
11     int f=1,x=0;char ch=getchar();
12     while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)f=-1;ch=getchar();}
13     while(ch<=‘9‘&&ch>=‘0‘){x=(x<<3)+(x<<1)+ch-‘0‘;ch=getchar();}
14     return f*x;
15 }
16 int n,m,l[maxn],r[maxn],f[3005][3005];
17 signed main()
18 {
19 //    freopen("data","r",stdin);
20     n=read(),m=read();
21     for(int i=1;i<=n;i++)
22     {
23         int li=read(),ri=read();
24         l[li]++,r[ri]++;
25     }
26     for(int i=1;i<=m;i++)
27         l[i]=l[i-1]+l[i],r[i]=r[i-1]+r[i];
28 //    for(int i=1;i<=m;i++)cout<<l[i]<<
29     f[0][0]=1;
30     for(int i=1;i<=m;i++)
31     {
32         f[i][0]=f[i-1][0];
33         for(int j=1;j<=r[i];j++)
34             f[i][j]=(f[i-1][j]+f[i-1][j-1]*(r[i]-j+1)%mod)%mod;
35         for(int j=0;j<=min(i,n);j++)
36             for(int k=l[i-1];k<=min(i-j,l[i]-1);k++)
37                 f[i][j]=f[i][j]*(i-j-k)%mod;
38     }
39     printf("%lld\n",f[m][n]%mod);
40 }
41 /*
42 g++ 1.cpp -o 1
43 ./1
44
45 */

T3[C. big]「trie树」

性质:(a^b^c)<<d=(a<<d)^(b<<d)^(c<<d)

所以断点i就是使1~i先都左移再疑惑和

原文地址:https://www.cnblogs.com/casun547/p/11289091.html

时间: 2024-09-30 08:16:59

模拟11题解的相关文章

模拟11 题解

A. string 类似 HEOI2016排序 . 排序这道题因为只询问单点最终答案,二分答案, 将小于和大于等于答案的数分别设为0 1, 用线段树维护0 1的排序即可. 算法一: 本题中的1-n变成了0-25(即a-z),单点询问变成了全体询问. 仿照排序那道题的做法,线段树优化桶排序. 维护每个节点每个字符的cnt值,区间查询后区间赋值即可. 然而up和down函数都是$O(26)$的,加上修改操作最多被拆分为26个, 总的复杂度为$O(nlogn26^2)$. 需要卡常. 考场上码出了80

省选模拟11 题解

A. 组合数问题 还没想明白如何做,待补. B. recollection 因为原图为trie树,树上两个点的lcp长度等于两个点的lca深度. 考虑通过广义sam来维护两个点的lcs. 树上同时对应着一个$endpos$,树上两个点对应的$endpos$对应的广义sam上节点在后缀树的lca的$len$即为两个点的lcs长度. 所以对于原树上每个点,我们只关注它的子树在后缀树上能形成的$len$最大的lca. 树上$n$个点形成的lca集合,实际上等于dfs序上相邻的两点形成的lca集合. 所

JZOJ4316【NOIP2015模拟11.5】Isfind 题解

JZOJ4316 [NOIP2015模拟11.5]Isfind 题解 Description Input Output Sample Input 4 3    acbc    abc    cba    cc Sample Output Y    N    Y Data Constraint 思路: 题意要看懂,首先声明一下"子串"和"子序列"的区别,S的"子串"意思是在S中选取任意i个(0 < i <= |S|)连续字符组成的字符串

2019.11.11 题解报告

目录 2019.11.11 题解报告 答题情况: 各题目分析: 题目解析: 代码实现: 2019.11.11 题解报告 \[N^2\text{狂草1e5它不香嘛?}\] \[\text{By:Unluckierblock}\] 答题情况: 总成绩 : 169, 排名: 11 / 32 T1 : 0 T2 : 99 T3 : 70 各题目分析: 题目 1 : 预估成绩 : 60 实际成绩 : 0 考试用时 : 8 : 00 ~ 8 : 50 , 9 : 50 ~ 10 : 10 没有什么感觉 ,

HDU 1022 Train Problem I 模拟栈题解

火车进站,模拟一个栈的操作,额外的栈操作,查看是否能按照规定顺序出栈. 数据量很少,故此题目很容易AC. 直接使用数组模拟就好. #include <stdio.h> const int MAX_N = 10; char inOrder[MAX_N], outOrder[MAX_N], stk[MAX_N]; bool rs[MAX_N<<2]; int n; int main() { while (scanf("%d", &n) != EOF) { s

10-4国庆节第七场模拟赛题解

10-4 国庆节第七场模拟赛题解 T1工厂 (factory) 水 #include<iostream> #include<cstdio> #define int long long using namespace std; inline int read(){ int sum=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9'){ if(ch=='-')f=-1; ch=getchar(); } while(ch>='0

2018-10-25 模拟测试题解

目录 问题 A: 魏传之长坂逆袭 题目描述 输入 输出 样例输入 样例输出 题解 问题 B: 蜀传之单刀赴会 题目描述 [问题描述] 输入 输出 样例输入 样例输出 题解 问题 C: 吴传之火烧连营 [题目背景] [问题描述] 输入 输出 样例输入 样例输出 [样例解释] [数据规模和约定] 题解 本篇题解也发表于zwcblog作者是同一个人 问题 A: 魏传之长坂逆袭 题目描述 众所周知,刘备在长坂坡上与他的一众将领各种开挂,硬生生从曹操手中逃了出去,随后与孙权一起火烧赤壁.占有荆益.成就霸业

10月15日模拟赛题解

10月15日模拟赛题解 A 树 Description 给定一棵 \(n\) 个节点的树,每个节点有两个参数 \(a,~b\),对于每个节点,求子树中参数为 \(b\) 的所有节点的 \(a\) 之和 Limitations \(100\%\) \(1 \leq b \leq n \leq 10^5,~a \leq 1000\) \(60\%\) \(1 \leq b,n\leq 1000\) \(30\%\) \(1 \leq b, n \leq 10\) Solution 对于 \(30\%

CPPU程序设计训练营清明天梯模拟赛题解

感谢大家今天来做题 比赛地址:http://202.206.177.79/contest/8 由于博主比较菜,没做完所有题目,这里暂时仅提供前两部分的题解. 为了节约篇幅,题目及数据描述不再赘述,如有需求,请移步OJ查看. 感谢大家的辛苦付出,但是从这次比赛的结果来看,前行之路还非常非常漫长呐. 我寂寞的时候,会害怕踏出第一步.不会想到要去做什么事,所以,可能没有发觉很多很多的东西吧.--<夏目友人帐> 第一阶段 L1-1 天梯赛座位分配 (20分) 通过率:2.56% \(\;\;\) 通过