NOIP模拟测试11

这次考试T1想到了正解没有去实现,然后就死了,不过我估计就算想到正解也会挂(26^2和暴力一个分),肝了两个小时T2屁都没蹦出来,T3没有搞清那个式子的含义。

(不过一分没挂)

T1:string

开26棵线段树维护,还有一种更快的方法:对于每个树上的节点,只有左右儿子字符相同时才更新,不然不更新,这种打法将26换成了较小的常数,并且不需要memset,真是出家旅行必备骗分之良器

 1 #include <bits/stdc++.h>
 2 
 3 typedef long long LL;
 4 
 5 inline int rd() {
 6     int a = 1, b = 0; char c = getchar();
 7     while (!isdigit(c)) a = c == '-' ? 0 : 1, c = getchar();
 8     while (isdigit(c)) b = b * 10 + c - '0', c = getchar();
 9     return a ? b : -b;
10 }
11 
12 const int N = 100000 + 2333;
13 
14 int n, m; char str[N];
15 
16 int same[N * 3];
17 
18 #define ls(p) p << 1
19 #define rs(p) p << 1 | 1
20 
21 void pushup(int p) {
22     if (same[ls(p)] == same[rs(p)])
23         same[p] = same[ls(p)];
24     else same[p] = 0;
25 }
26 
27 void pushdown(int p) {
28     if (same[p])
29         same[ls(p)] = same[rs(p)] = same[p];
30 }
31 
32 void build(int p, int L, int R) {
33     if (L == R) return (void)(same[p] = str[L]);
34     int mid = (L + R) >> 1;
35     build(ls(p), L, mid);
36     build(rs(p), mid + 1, R);
37     pushup(p);
38 }
39 
40 void change(int p, int l, int r, int v, int L, int R) {
41     if (l <= L && r >= R) return (void)(same[p] = v);
42     pushdown(p); int mid = (L + R) >> 1;
43     if (l <= mid) change(ls(p), l, r, v, L, mid);
44     if (r > mid) change(rs(p), l, r, v, mid + 1, R);
45     pushup(p);
46 }
47 
48 int que[233];
49 
50 void query(int p, int l, int r, int L, int R) {
51     if (l <= L && r >= R && same[p])
52         return (void)(que[same[p]] += (R - L + 1));
53     pushdown(p); int mid = (L + R) >> 1;
54     if (l <= mid) query(ls(p), l, r, L, mid);
55     if (r > mid) query(rs(p), l, r, mid + 1, R);
56 }
57 
58 void write(int p, int L, int R) {
59     if (L == R) return (void)(putchar(same[p]));
60     pushdown(p); int mid = (L + R) >> 1;
61     write(ls(p), L, mid);
62     write(rs(p), mid + 1, R);
63 }
64 
65 int main() {
66     scanf("%d%d%s", &n, &m, str + 1);
67     build(1, 1, n);
68     while (m--) {
69         int l, r, x; scanf("%d%d%d", &l, &r, &x);
70         for (int i = 'a'; i <= 'z'; ++i) que[i] = 0;
71         query(1, l, r, 1, n);
72         if (x == 1) {
73             for (int i = 'a', lst = l; i <= 'z'; ++i) if (que[i])
74                 change(1, lst, lst + que[i] - 1, i, 1, n), lst = lst + que[i];
75         } else {
76             for (int i = 'z', lst = l; i >= 'a'; --i) if (que[i])
77                 change(1, lst, lst + que[i] - 1, i, 1, n), lst = lst + que[i];
78         }
79     }
80     write(1, 1, n);
81     return 0;
82 }
Orz
  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #define clr(x) memset(x,0,sizeof(x))
  5 using namespace std;
  6 const int MAXN=800100;
  7 int N,M;
  8 char s[MAXN];
  9 int t[30];
 10 char wd[MAXN*4];
 11 int cnt[MAXN*4][30],tg[MAXN];
 12 bool fg[MAXN*4];
 13 void bt(int p,int l,int r){
 14     tg[p]=-1;
 15     if(l==r){
 16         wd[p]=s[l];
 17         cnt[p][s[l]-'a']=1;
 18         return;
 19     }
 20     int mid=(l+r)>>1;
 21     bt(p<<1,l,mid);
 22     bt(p<<1|1,mid+1,r);
 23     int fgg=0;
 24     for(int i=0;i<26;++i){
 25         cnt[p][i]=cnt[p<<1][i]+cnt[p<<1|1][i];
 26         fgg+=(cnt[p][i]!=0);
 27     }
 28     fg[p]=(fgg==1);
 29 }
 30 void get(int p,int l,int r,int ll,int rr,int out[]){
 31     if(ll<=l && r<=rr){
 32         for(int i=0;i<26;++i)
 33             out[i]+=cnt[p][i];
 34         return;
 35     }
 36     if(tg[p]!=-1){
 37         int id=tg[p];
 38         int mid=(l+r)>>1;
 39         clr(cnt[p<<1]);
 40         clr(cnt[p<<1|1]);
 41         cnt[p<<1][id]=mid-l+1;
 42         cnt[p<<1|1][id]=r-(mid+1)+1;
 43         tg[p<<1]=tg[p<<1|1]=id;
 44         wd[p<<1]=wd[p<<1|1]=id+'a';
 45         fg[p<<1]=fg[p<<1|1]=1;
 46         tg[p]=-1;
 47     }
 48     int mid=(l+r)>>1;
 49     if(ll<=mid)
 50         get(p<<1,l,mid,ll,rr,out);
 51     if(rr>mid)
 52         get(p<<1|1,mid+1,r,ll,rr,out);
 53 }
 54 void cover(int p,int l,int r,int ll,int rr,int id){
 55     if(ll<=l && r<=rr){
 56         clr(cnt[p]);
 57         cnt[p][id]=r-l+1;
 58         tg[p]=id;
 59         wd[p]=id+'a';
 60         fg[p]=1;
 61         return;
 62     }
 63     if(tg[p]!=-1){
 64         int id=tg[p];
 65         int mid=(l+r)>>1;
 66         clr(cnt[p<<1]);
 67         clr(cnt[p<<1|1]);
 68         cnt[p<<1][id]=mid-l+1;
 69         cnt[p<<1|1][id]=r-(mid+1)+1;
 70         tg[p<<1]=tg[p<<1|1]=id;
 71         wd[p<<1]=wd[p<<1|1]=id+'a';
 72         fg[p<<1]=fg[p<<1|1]=1;
 73         tg[p]=-1;
 74     }
 75     int mid=(l+r)>>1;
 76     if(ll<=mid)
 77         cover(p<<1,l,mid,ll,rr,id);
 78     if(rr>mid)
 79         cover(p<<1|1,mid+1,r,ll,rr,id);
 80     int fgg=0;
 81     for(int i=0;i<26;++i){
 82         cnt[p][i]=cnt[p<<1][i]+cnt[p<<1|1][i];
 83         fgg+=(cnt[p]!=0);
 84     }
 85     fg[p]=(fgg==1);
 86 }
 87 void dfs(int p,int l,int r){
 88     if(l==r){
 89         printf("%c",wd[p]);
 90         return;
 91     }
 92     if(tg[p]!=-1){
 93         int id=tg[p];
 94         int mid=(l+r)>>1;
 95         clr(cnt[p<<1]);
 96         clr(cnt[p<<1|1]);
 97         cnt[p<<1][id]=mid-l+1;
 98         cnt[p<<1|1][id]=r-(mid+1)+1;
 99         tg[p<<1]=tg[p<<1|1]=id;
100         wd[p<<1]=wd[p<<1|1]=id+'a';
101         fg[p<<1]=fg[p<<1|1]=1;
102         tg[p]=-1;
103     }
104     int mid=(l+r)>>1;
105     dfs(p<<1,l,mid);
106     dfs(p<<1|1,mid+1,r);
107 }
108 int main(){
109     scanf("%d%d",&N,&M);
110     char c=getchar();
111     int len=0;
112     while(c<'a' || c>'z')
113         c=getchar();
114     while(c<='z' && c>='a'){
115         s[++len]=c;
116         c=getchar();
117     }
118     bt(1,1,N);
119     for(int i=1;i<=M;++i){
120         int l,r,opt;
121         scanf("%d%d%d",&l,&r,&opt);
122         clr(t);
123         get(1,1,N,l,r,t);
124         if(opt==0){
125             for(int i=25;i>=0;--i){
126                 if(t[i])
127                     cover(1,1,N,l,l+t[i]-1,i);
128                 l+=t[i];
129             }
130         }
131         else{
132             for(int i=0;i<26;++i){
133                 if(t[i])
134                     cover(1,1,N,l,l+t[i]-1,i);
135                 l+=t[i];
136             }
137         }
138     }
139     dfs(1,1,N);
140 }
正常AC代码
  1 #include<bits/stdc++.h>
  2 #define MAXN 100005
  3 #define cri const register int
  4 #define pt puts("----------------")
  5 using namespace std;
  6 int now[27];
  7 char s[MAXN];
  8 struct Seg_tree{
  9     int t[MAXN*4][27],f[MAXN*4];
 10     #define ls k<<1
 11     #define rs k<<1|1
 12     void change(cri k,cri l,cri r,cri gl,cri gr,cri val)
 13     {
 14         if(l>=gl&&r<=gr)
 15         {
 16             memset(t[k],0,sizeof(t[k]));
 17             t[k][val]=r-l+1;
 18             f[k]=val;
 19             return ;
 20         }
 21         register int mid=l+r>>1;
 22         if(f[k])
 23         {
 24             register int mid=l+r>>1;
 25             memset(t[ls],0,sizeof(t[ls]));
 26             memset(t[rs],0,sizeof(t[rs]));
 27             register int p=f[k];f[k]=0;
 28             t[ls][p]=mid-l+1;
 29             t[rs][p]=r-mid;
 30             f[ls]=f[rs]=p;
 31         }
 32         if(gl<=mid)change(ls,l,mid,gl,gr,val);
 33         if(gr>mid)change(rs,mid+1,r,gl,gr,val);
 34         t[k][1]=t[ls][1]+t[rs][1];
 35         t[k][2]=t[ls][2]+t[rs][2];
 36         t[k][3]=t[ls][3]+t[rs][3];
 37         t[k][4]=t[ls][4]+t[rs][4];
 38         t[k][5]=t[ls][5]+t[rs][5];
 39         t[k][6]=t[ls][6]+t[rs][6];
 40         t[k][7]=t[ls][7]+t[rs][7];
 41         t[k][8]=t[ls][8]+t[rs][8];
 42         t[k][9]=t[ls][9]+t[rs][9];
 43         t[k][10]=t[ls][10]+t[rs][10];
 44         t[k][11]=t[ls][11]+t[rs][11];
 45         t[k][12]=t[ls][12]+t[rs][12];
 46         t[k][13]=t[ls][13]+t[rs][13];
 47         t[k][14]=t[ls][14]+t[rs][14];
 48         t[k][15]=t[ls][15]+t[rs][15];
 49         t[k][16]=t[ls][16]+t[rs][16];
 50         t[k][17]=t[ls][17]+t[rs][17];
 51         t[k][18]=t[ls][18]+t[rs][18];
 52         t[k][19]=t[ls][19]+t[rs][19];
 53         t[k][20]=t[ls][20]+t[rs][20];
 54         t[k][21]=t[ls][21]+t[rs][21];
 55         t[k][22]=t[ls][22]+t[rs][22];
 56         t[k][23]=t[ls][23]+t[rs][23];
 57         t[k][24]=t[ls][24]+t[rs][24];
 58         t[k][25]=t[ls][25]+t[rs][25];
 59         t[k][26]=t[ls][26]+t[rs][26];
 60     }
 61     void query(cri k,cri l,cri r,cri gl,cri gr)
 62     {
 63         if(l>=gl&&r<=gr)
 64         {
 65             for(register int i=1;i<=26;i++)now[i]+=t[k][i];
 66             return ;
 67         }
 68         register int mid=l+r>>1;
 69         if(f[k])
 70         {
 71             register int mid=l+r>>1;
 72             memset(t[ls],0,sizeof(t[ls]));
 73             memset(t[rs],0,sizeof(t[rs]));
 74             register int p=f[k];f[k]=0;
 75             t[ls][p]=mid-l+1;
 76             t[rs][p]=r-mid;
 77             f[ls]=f[rs]=p;
 78         }
 79         if(gl<=mid)query(ls,l,mid,gl,gr);
 80         if(gr>mid)query(rs,mid+1,r,gl,gr);
 81         return ;
 82     }
 83     void Build(cri k,cri l,cri r)
 84     {
 85         if(l==r)
 86         {
 87             t[k][s[l-1]-'a'+1]=1;
 88             return ;
 89         }
 90         register int mid=l+r>>1;
 91         Build(ls,l,mid);
 92         Build(rs,mid+1,r);
 93         t[k][1]=t[ls][1]+t[rs][1];
 94         t[k][2]=t[ls][2]+t[rs][2];
 95         t[k][3]=t[ls][3]+t[rs][3];
 96         t[k][4]=t[ls][4]+t[rs][4];
 97         t[k][5]=t[ls][5]+t[rs][5];
 98         t[k][6]=t[ls][6]+t[rs][6];
 99         t[k][7]=t[ls][7]+t[rs][7];
100         t[k][8]=t[ls][8]+t[rs][8];
101         t[k][9]=t[ls][9]+t[rs][9];
102         t[k][10]=t[ls][10]+t[rs][10];
103         t[k][11]=t[ls][11]+t[rs][11];
104         t[k][12]=t[ls][12]+t[rs][12];
105         t[k][13]=t[ls][13]+t[rs][13];
106         t[k][14]=t[ls][14]+t[rs][14];
107         t[k][15]=t[ls][15]+t[rs][15];
108         t[k][16]=t[ls][16]+t[rs][16];
109         t[k][17]=t[ls][17]+t[rs][17];
110         t[k][18]=t[ls][18]+t[rs][18];
111         t[k][19]=t[ls][19]+t[rs][19];
112         t[k][20]=t[ls][20]+t[rs][20];
113         t[k][21]=t[ls][21]+t[rs][21];
114         t[k][22]=t[ls][22]+t[rs][22];
115         t[k][23]=t[ls][23]+t[rs][23];
116         t[k][24]=t[ls][24]+t[rs][24];
117         t[k][25]=t[ls][25]+t[rs][25];
118         t[k][26]=t[ls][26]+t[rs][26];
119     }
120 }T;
121 inline int Rd()
122 {
123     register int x=0,f=1;register char c=getchar();
124     while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
125     while(c>='0'&&c<='9'){x=x*10+c-48;c=getchar();}
126     return x*f;
127 }
128 int n,m;
129 int main()
130 {
131     scanf("%d%d%s",&n,&m,s);
132     T.Build(1,1,n);
133     while(m--)
134     {
135         memset(now,0,sizeof(now));
136         register int l,r,x,t,k;
137         l=Rd();r=Rd();x=Rd();
138         k=l;
139         T.query(1,1,n,l,r);
140         if(x)
141         {
142             t=1;
143             while(t<=26)
144             {
145                 while(!now[t]&&t<=26)++t;
146                 T.change(1,1,n,k,k+now[t]-1,t);
147                 k+=now[t];
148                 now[t]=0;
149             }
150         }
151         else 
152         {
153             t=26;
154             while(t>=0)
155             {
156                 while(!now[t]&&t>=0)--t;
157                 T.change(1,1,n,k,k+now[t]-1,t);
158                 k+=now[t];
159                 now[t]=0;
160             }
161         }
162     }
163     for(int i=1;i<=n;i++)
164     {
165         memset(now,0,sizeof(now));
166         T.query(1,1,n,i,i);
167         for(int j=1;j<=26;j++)
168             if(now[j])
169             {
170                 putchar('a'+j-1);
171                 break;
172             }
173     }
174     puts("");
175     return 0;
176 }
我的AC代码。
 1 #include<cstdio>
 2 char s[100005],bucx[100005];int bucr[100005],buc[127],n,m;
 3 main(){
 4     scanf("%d%d%s",&n,&m,s+1);bucr[n+1]=n+1;
 5     for(int i=1;i<=n;++i)bucr[i]=i,bucx[i]=s[i];
 6     for(int i=1,l,r,x;i<=m;++i){
 7         scanf("%d%d%d",&l,&r,&x);
 8         int j;for(j=l;!bucr[j];--j);
 9         int k=bucr[j]+1;if(j!=l)buc[bucx[j]]+=bucr[j]-l+1,bucr[j]=l-1;else k=j;
10         while(bucr[k]<=r){
11             buc[bucx[k]]+=bucr[k]-k+1;
12             int lst=k;k=bucr[k]+1;bucr[lst]=0;
13         }
14         if(k<=r)buc[bucx[k]]+=r-k+1,bucr[r+1]=bucr[k],bucx[r+1]=bucx[k],bucr[k]=0;
15         if(x)for(char ch='a';ch<='z';++ch)if(buc[ch])bucr[l]=l+buc[ch]-1,bucx[l]=ch,l=bucr[l]+1,buc[ch]=0;
16         if(!x)for(char ch='z';ch>='a';--ch)if(buc[ch])bucr[l]=l+buc[ch]-1,bucx[l]=ch,l=bucr[l]+1,buc[ch]=0;
17     }
18     for(int i=1;i<=n;i=bucr[i]+1)for(int j=i;j<=bucr[i];++j)putchar(bucx[i]);
19 }
300ms做法

Orz wd暴力QJ神仙打法

T2:matrix

dp状态设的很神 f[i][j]表示前i列满足j个有区间且满足题意的方案数

先设ls[i]表示右端点在前i列的左区间的方案数,rs[i]表示左端点在前i列的右区间的方案数

然后就可以转移了,考虑列数增还是不增

不增:f[i+1][j]+=f[i][j]

增:f[i+1][j+1]+=f[i][j]*(rs[i+1]-j)

注意左侧区间我们并没有考虑,实际考虑,供我们选的列有i-j个,前一个状态已经选了ls[i-1]个,新增状态有ls[i]-ls[i-1]个。

用新增状态塞满可选状态并要考虑顺序,同时还有一个合法状态的判定然后就没啦

说起来很简单,但状态真的难想,但也不无道理。

这个题紧紧扣住列,而与具体是哪行无关,所以i,j都与列有关,同时为了方便转移,我们抓住一侧的区间,状态及其转移就显然了。

还是要抓住题目核心性质。

 1 #include<bits/stdc++.h>
 2 #define MAXN 3005
 3 #define int long long
 4 using namespace std;
 5 const int mod=998244353;
 6 int f[MAXN][MAXN],ls[MAXN],rs[MAXN],l[MAXN],r[MAXN],A[MAXN][MAXN];
 7 signed main()
 8 {
 9     int n,m;
10     scanf("%lld%lld",&n,&m);
11     for(int i=1;i<=n;i++)
12     {
13         scanf("%lld%lld",&l[i],&r[i]);
14         ls[l[i]]++;rs[r[i]]++;
15     }
16     for(int i=1;i<=m;i++)ls[i]+=ls[i-1],rs[i]+=rs[i-1];
17     A[0][0]=A[0][1]=1;f[0][0]=1;
18     for(int i=1;i<=m;i++)
19     {
20         A[i][0]=1;A[i][1]=i;
21         for(int j=2;j<=i;j++)
22             A[i][j]=A[i][j-1]*(i-j+1)%mod;
23     }
24     for(int i=0;i<=m;i++)
25     {
26         for(int j=0;j<=min(i,n);j++)
27         {
28             if(i-j<ls[i])break;
29             (f[i][j]*=A[i-j-ls[i-1]][ls[i]-ls[i-1]])%=mod;
30             (f[i+1][j]+=f[i][j])%=mod;
31             (f[i+1][j+1]+=f[i][j]*max(0ll,rs[i+1]-j))%=mod;
32         }
33     }
34     cout<<f[m][n]<<endl;
35     return 0;
36 }
View Code

 

T3:big

这题的难点在于如何转化题意

这个式子实际上就是x的逻辑左移,然后后面就显然了,开一颗Trie树,求最大值即可

 1 #include<bits/stdc++.h>
 2 #define re register
 3 using namespace std;
 4 const int MAXN=100000;
 5 int n,maxx,val,sum[MAXN],psum[MAXN],num;
 6     int ch[MAXN*50][2],tot;
 7     void insert(const int x)
 8     {
 9         re int p=0;
10         for(int i=n-1;i>=0;i--)
11         {
12             re int k=(x>>i)&1;
13             if(!ch[p][k])ch[p][k]=++tot;
14             p=ch[p][k];
15         }
16         return ;
17     }
18     void Getans(const int x,int val,int dep)
19     {
20         if(!ch[x][0]&&!ch[x][1])
21         {
22             if(val==maxx)num++;
23             else if(val>maxx)maxx=val,num=1;
24             return ;
25         }
26         if(ch[x][0]&&ch[x][1]){
27             Getans(ch[x][0],val,dep+1);
28             Getans(ch[x][1],val,dep+1);
29             return ;
30         }
31         if(!ch[x][0]||!ch[x][1]){
32             Getans(ch[x][0]|ch[x][1],val+(1<<(n-dep-1)),dep+1);
33         }
34         return ;
35     }
36 int main()
37 {
38     int m;
39     scanf("%d%d",&n,&m);
40     for(int i=1;i<=m;i++)
41     {
42         register int a,k=0;scanf("%d",&a);
43         sum[i]=sum[i-1]^a;
44         if((a>>(n-1))&1)k=1;
45         (k+=a<<1)&=((1<<n)-1);
46         psum[i]=psum[i-1]^k;
47     }
48     for(int i=0;i<=m;i++)
49         insert(psum[i]^(sum[m]^sum[i]));
50     Getans(0,0,0);
51     cout<<maxx<<endl<<num<<endl;
52     return 0;
53 }
View Code

总结:

1.分析题目核心性质

2.转化题意

3.卡常

 

原文地址:https://www.cnblogs.com/hzoi-kx/p/11286735.html