考试总结 NOIP模拟5 (20210608)

Posted JYFHYX

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了考试总结 NOIP模拟5 (20210608)相关的知识,希望对你有一定的参考价值。

考试题越来越难了,但每次考试都是对这个知识的又一次新的认识,不断地考试,改题,考试,改题才能更快的提升自己;

T1string

题目描述:给定一个由小写字母组成的字符串 s。有 m 次操作,每次操作给定 3 个参数 l,r,x。如果 x=1,将 s[l]~s[r]升序排序;如果 x=0,将 s[l]~s[r]降序排序。你需要求出最终序列

输入格式:

第一行两个整数 n,m。
第二行一个字符串 s。
接下来 m 行每行三个整数 l,r,x。

输出格式:

1行一个字符串表示答案

样例输入:
 
5 2
cabcd
1 3 1
3 5 0
样例输出:
abdcc
数据范围:对于40%n,m<=1000,对于100%n,m<=100000
solution:
首先呢,这个题的40%的分数是非常轻松就可以拿到的,只要进行m次快排就可以拿掉40,由于快排的复杂度是O(n*log(n))的
所以,用快排整个题的时间复杂度是O(m*n*log(n)),这显然是不合法的,
暴力算法还可以用桶进行优化,记录这个区间每个字母出现的次数,可以把时间复杂度缩小到O(m*n)
好,那么现在开始说正解:
这个题看起来像排序,但这道题目的本质其实是线段树区间查询和区间修改,,时间复杂度都是log(n),并且我们发现,一共只有26种字符,所以另一个
时间复杂度就出来了O(m*log(n)*26);
好,那么为啥是区间查询和区间修改呢;
我们发现这m次操作里面,每一次都是让这个区间里面的值满足单调性,并且相同的字符会挨在一起,也就是说当啊x==1时2的位置就应该在1出现的次数+1到1出现的次数+2出现的次数;
如果x==0,就把他们反过过来,那么赋值也很好实现了,直接用区间修改,把第l到r的区间,赋值成应该的值;
最后直接遍历输出 完美;
  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 {
  7     int x=0,f=1;
  8     char ch=getchar();
  9     while(ch<\'0\'||ch>\'9\')
 10     {
 11         if(ch==\'-\')
 12         f=-1;
 13         ch=getchar();
 14     }
 15     while(ch>=\'0\'&&ch<=\'9\')
 16     {
 17         x=(x<<1)+(x<<3)+(ch^48);
 18         ch=getchar();
 19     }
 20     return x*f;
 21 }
 22 int n,m;
 23 char s[100001];
 24 int a[100001];
 25 int sum[27];
 26 struct seg_tree{
 27     int l,r;
 28     int v,lazy;
 29 }tr[1000001];
 30 inline void pushup(int id)
 31 {
 32     if(tr[lid].lazy==tr[rid].lazy)
 33     tr[id].lazy=tr[lid].lazy;
 34     else
 35     tr[id].lazy=-1;
 36 }
 37 inline void pushdown(int id)
 38 {
 39     if(tr[id].lazy!=-1)
 40     {
 41         tr[lid].lazy=tr[id].lazy;
 42         tr[rid].lazy=tr[id].lazy;   
 43     }
 44     else
 45     tr[id].lazy=-1;
 46 }
 47 inline void build(int id,int l,int r)
 48 {
 49     tr[id].lazy=-1;
 50     tr[id].l=l;
 51     tr[id].r=r;
 52     if(tr[id].l==tr[id].r)
 53     {
 54         tr[id].lazy=a[l];
 55         return ;
 56     }
 57     int mid=(l+r)>>1;
 58     build(lid,l,mid);
 59     build(rid,mid+1,r);
 60     pushup(id);
 61 }
 62 inline void make(int id,int l,int r)
 63 {
 64     if(l<=tr[id].l&&tr[id].r<=r)
 65     {
 66         if(tr[id].lazy!=-1)
 67         {
 68             sum[tr[id].lazy]+=tr[id].r-tr[id].l+1; 
 69             return;
 70         }
 71     }
 72     pushdown(id);
 73     int mid=(tr[id].l+tr[id].r)>>1;
 74     if(l<=mid)make(lid,l,r);
 75     if(mid+1<=r)make(rid,l,r);
 76 }
 77 inline void change(int id,int l,int r,int vv)
 78 {
 79     if(l>r) return;
 80     if(l<=tr[id].l&&tr[id].r<=r)
 81     {    
 82         tr[id].lazy=vv; 
 83         return;    
 84     } 
 85     int mid=(tr[id].l+tr[id].r)>>1;
 86     if(l<=mid)
 87     change(lid,l,r,vv);
 88     if(mid+1<=r)
 89     change(rid,l,r,vv);
 90     pushup(id);
 91 }
 92 inline void query(int id)
 93 {
 94     if(tr[id].lazy!=-1)
 95     {
 96         for(register int i=1;i<=tr[id].r-tr[id].l+1;++i)
 97         putchar(tr[id].lazy+\'a\');
 98         return;
 99     }
100     query(lid);
101     query(rid);
102 }
103 int main()
104 {
105     n=read(),m=read();
106     scanf("%s",s+1);
107     for(int i=1;i<=n;i++)
108     {
109         a[i]=s[i]-\'a\';
110     }
111     build(1,1,n);
112     for(int i=1;i<=m;i++)
113     {
114         memset(sum,0,sizeof(sum));
115         int l,r,x;
116         l=read(),r=read(),x=read();
117         make(1,l,r);
118         if(x)
119         {
120             int L=l;
121             for(int j=0;j<26;j++)
122             {
123                 change(1,L,L+sum[j]-1,j);
124                 L+=sum[j];
125             }
126         }
127         else
128         {
129             int L=l;
130             for(int j=25;j>=0;j--)
131             {
132                 change(1,L,L+sum[j]-1,j);
133                 L+=sum[j];
134             }
135         }
136     }
137     query(1);
138 }
t1代码

T2matrix

题目描述:

求出满足以下条件的 n*m 的 01 矩阵个数:
(1)第 i 行第 1~li 列恰好有 1 个 1。 (li+1到ri-1不能放1)(2)第 i 行第 ri~m 列恰好有 1 个 1。
(3)每列至多有 1 个 1。

输入格式:第一行两个整数 n,m。接下来 n 行每行 2 个整数 li,ri。

输出格式:一行一个整数表示答案。对 998244353 取模。

样例输入:

2 6

2 4

5 6

样例输出:

12

数据范围:

对于 20%的数据,n,m<=12。
对于 40%的数据,n,m<=50。
对于 70%的数据,n,m<=300。
对于 100%的数据,n,m<=3000,1<=li<ri<=m。

solution:

考试的时候,同学们都只拿了暴力分,这道题目想出正解,至少在我这种苣弱看来考场上是很难了(先干大佬去了)

以上是关于考试总结 NOIP模拟5 (20210608)的主要内容,如果未能解决你的问题,请参考以下文章

「考试」noip模拟5

Test20171009 考试总结 NOIP模拟赛

6.17考试总结(NOIP模拟8)

NOIP 模拟 6 考试总结

NOIP 模拟 7 考试总结

11.1noip模拟考试总结——众人AK,唯我爆零