省选模拟六 题解

写在前面:

考试不在状态

码题的时候根本不知道自己在码什么

$T2$转移写少暴露出对$SAM$理解不深刻

根本没有理解

感觉吃枣药丸

A. Yist

标签:

根号思想

题解:

不难发现式子其实是个等比数列求和

直接模拟显然会被菊花图卡

考虑对于每个点按度数是否大于$sqrt{n}$分为重点和轻点

对于每个点$x$维护$g[x]$代表周围所以轻点的贡献和

每次轻点更改时暴力把周围的$g$更新

对于重点在操作$x$时暴力统计即可

复杂度$O(nsqrt{n})$

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int N=2e5+10,mod=998244353,inv2=499122177;
 4 int S,ans,tot,n,m,k,w[N],bin[N],inv[N],d[N],g[N],to[N],ne[N],s[N],head[N],mark[N];
 5 vector<int>e[N];
 6 int qpow(int x,int y,int z)
 7 {
 8         int sum=1;
 9         while(y)
10         {
11                 if(y&1) sum=1ll*sum*x%z;
12                 y>>=1;
13                 x=1ll*x*x%z;
14         }
15         return sum;
16 }
17 void add(int x,int y)
18 {
19         d[x]++,d[y]++;
20         to[++tot]=y;
21         ne[tot]=head[x];
22         head[x]=tot;
23 }
24 int main()
25 {
26         //freopen("1.in","r",stdin);
27         bin[0]=1;
28         for(int i=1;i<=200000;i++) bin[i]=(bin[i-1]+bin[i-1])%mod;
29         for(int i=0;i<=200000;i++) inv[i]=qpow(bin[i]-1,mod-2,mod);
30         while(scanf("%d%d%d",&n,&m,&k)!=EOF)
31         {
32                 S=sqrt(n);
33                 for(int i=1;i<=n;i++) scanf("%d",&w[i]);
34                 for(int i=1;i<=k;i++) scanf("%d",&s[i]),mark[s[i]]++;
35                 for(int i=1,x,y;i<=m;i++)
36                 {
37                         scanf("%d%d",&x,&y);
38                         add(x,y),add(y,x);
39                 }
40                 for(int i=1;i<=n;i++)
41                 {
42                         if(mark[i])
43                         {
44                                 for(int j=head[i];j;j=ne[j])
45                                 {
46                                         if(!mark[to[j]])
47                                         {
48                                                 ans=-1;
49                                                 break;
50                                         }
51                                 }
52                         }
53                 }
54                 if(ans==-1) puts("-1");
55                 else 
56                 {
57                         for(int i=1;i<=n;i++) w[i]=1ll*w[i]*bin[mark[i]]%mod*inv[mark[i]]%mod;
58                         for(int i=1;i<=n;i++)
59                         {
60                                 for(int j=head[i];j;j=ne[j])
61                                 {
62                                         if(d[to[j]]>S) e[i].push_back(to[j]);
63                                         else g[i]=(g[i]+w[to[j]])%mod;
64                                 }
65                         }
66                         for(int i=1,x;i<=k;i++)
67                         {
68                                 x=s[i];
69                                 for(int j=0;j<e[x].size();j++) ans=(ans+w[e[x][j]])%mod;
70                                 ans=(ans+g[x])%mod;
71                                 w[x]=1ll*w[x]*inv2%mod;
72                                 if(d[x]>S) continue;
73                                 for(int j=head[x];j;j=ne[j]) g[to[j]]=(g[to[j]]-w[x])%mod;
74                         }
75                         printf("%d
",(ans+mod)%mod);
76                 }
77                 ans=tot=0;
78                 for(int i=1;i<=n;i++) e[i].clear(),head[i]=d[i]=g[i]=mark[i]=0;
79         }
80         return 0;
81 }
T1

B. Ernd

标签:

$SAM$+$DP$

题解:

暴力建出$SAM$在$SAM$和$fail$树上$Dp$是$O(n^2)$

其实不必存储当前的长度

因为继续往下走的单次贡献一定没有当前的优

所以贪心在当前点操作到最长的长度即可

复杂度$O(m)$,$m$为$SAM$和$fail$树上的边数

 1 #include <bits/stdc++.h>
 2 #define int long long
 3 using namespace std;
 4 const int N=16e5+10;
 5 int tot,n,head[N],to[N],ne[N],dp[N];
 6 char s[N];
 7 struct SAM
 8 {
 9         int last,cnt,f[N];
10         vector<int>v[N];
11         struct node{int fa,len,ch[26];}a[N];
12         void extend(int c)
13         {
14                 int p=last,np=last=++cnt;
15                 a[np].len=a[p].len+1;
16                 f[np]=1;
17                 for(;p&&!a[p].ch[c];p=a[p].fa) a[p].ch[c]=np;
18                 if(!p) a[np].fa=1;
19                 else
20                 {
21                         int q=a[p].ch[c];
22                         if(a[q].len==a[p].len+1) a[np].fa=q;
23                         else
24                         {
25                                 int nq=++cnt;
26                                 a[nq]=a[q];
27                                 a[nq].len=a[p].len+1;
28                                 a[q].fa=a[np].fa=nq;
29                                 for(;a[p].ch[c]==q;p=a[p].fa) a[p].ch[c]=nq;
30                         }
31                 }
32         }
33         void dfs(int x)
34         {
35                 for(int i=0;i<v[x].size();i++)
36                 {
37                         dfs(v[x][i]);
38                         f[x]+=f[v[x][i]];
39                 }
40         }
41 }S;
42 void add(int x,int y)
43 {
44         to[++tot]=y;
45         ne[tot]=head[x];
46         head[x]=tot;
47 }
48 int dfs(int x,int y)
49 {
50         if(x==n) return 0;
51         if(dp[y]!=-1) return dp[y];
52         for(int i=head[y];i;i=ne[i])
53         {
54                 dp[y]=max(dp[y],dfs(S.a[to[i]].len,to[i])+S.f[to[i]]*(S.a[to[i]].len-x));
55         }
56         return dp[y];
57 }
58 signed main()
59 {
60         //freopen("2.in","r",stdin);
61         //freopen("2.out","w",stdout);
62         memset(dp,-1,sizeof(dp));
63         S.last=S.cnt=1;
64         scanf("%lld%s",&n,s+1);
65         for(int i=1;i<=n;i++) S.extend(s[i]-'a');
66         for(int i=1;i<=S.cnt;i++)
67         {
68                 if(i^1)
69                 {
70                         S.v[S.a[i].fa].push_back(i);
71                         add(S.a[i].fa,i);
72                 }
73                 for(int j=0;j<26;j++) if(S.a[i].ch[j]) add(i,S.a[i].ch[j]);
74         }
75         S.dfs(1);
76         printf("%lld
",dfs(0,1));
77         return 0;
78 }
T2

C. Sanrd

标签:

$BIT$的神仙题

题解:

一道$BIT$题打了200行+

可怕~

但这题的思路很棒

首先$LIS$和$LDS$的重复部分最多为$1$

考虑求出经过每个点的$LDS$个数$g[i]$

$$all=sumlimits_{i=1}^{n}g[i]$$

那么一个$LIS$集合${a_1,a_2...a_k}$

$$val=sumlimits_{i=1}^{k}g[a[i]]$$

这个$LIS$不合法当且仅当$val=all$

所以问题转化为了求出一个$LIS$序列满足$val!=all$

限制很单一,只要不等于就OK

所以可以对于每个点维护两个不同的$val$的方案

最后便一定有一个是合法的

  1 #include <bits/stdc++.h>
  2 #define int long long
  3 using namespace std;
  4 const int N=1e6+10;
  5 int mod[2]={998244353,(int)1e13+7};
  6 int k,L,R,al,n,p[N],c[N],h[N],f[2][N],g[N],q[N],vis[N],pre[N];
  7 struct node
  8 {
  9         int f,pos,pre;
 10         
 11 }a[N][2],dp[N][2];
 12 int read()
 13 {
 14         int sum,k=1;char s;
 15         while(s=getchar(),s<'0'||s>'9') if(s=='-') k=-1;sum=s-'0';
 16         while(s=getchar(),s>='0'&&s<='9') sum=sum*10+s-'0';
 17         return k*sum;
 18 }
 19 int lowbit(int x)
 20 {
 21         return x&-x;
 22 }
 23 void add(int x,int y,int z)
 24 {
 25         while(x<=n)
 26         {
 27                 if(c[x]<y)
 28                 {
 29                         c[x]=y;
 30                         h[x]=z;
 31                 }
 32                 else if(c[x]==y) (h[x]+=z)%=mod[k];
 33                 x+=lowbit(x);
 34         }
 35 }
 36 int get(int &y,int x)
 37 {
 38         int val=0,z=x;
 39         while(z)
 40         {
 41                 val=max(val,c[z]);
 42                 z-=lowbit(z);
 43         }
 44         while(x)
 45         {
 46                 if(c[x]==val) (y+=h[x])%=mod[k];
 47                 x-=lowbit(x);
 48         }
 49         return val;
 50 }
 51 void add1(int x,int y,int z)
 52 {
 53         while(x<=n+1)
 54         {
 55                 if(c[x]<y)
 56                 {
 57                         c[x]=y;
 58                         a[x][0]=dp[z][0];
 59                         a[x][1]=dp[z][1];
 60                 }
 61                 else if(c[x]==y)
 62                 {
 63                         if(a[x][0].f==-1) a[x][0]=dp[z][0];
 64                         else if(a[x][1].f==-1&&a[x][0].f!=dp[z][0].f) a[x][1]=dp[z][0];
 65                         if(a[x][0].f==-1) a[x][0]=dp[z][1];
 66                         else if(a[x][1].f==-1&&a[x][0].f!=dp[z][1].f) a[x][1]=dp[z][1];
 67                 }
 68                 x+=lowbit(x);
 69         }
 70 }
 71 int get1(int x,int y)
 72 {
 73         int val=0,z=x;
 74         while(z) 
 75         {
 76                 val=max(val,c[z]);
 77                 z-=lowbit(z);
 78         }
 79         while(x)
 80         {
 81                 if(val==c[x])
 82                 {
 83                         node S=a[x][0];(S.f+=g[y])%=mod[k];S.pre=S.pos;S.pos=y;
 84                         if(!val||a[x][0].f!=-1)
 85                         {
 86                                 S.f+=a[x][0].f==-1;
 87                                 if(dp[y][0].f==-1) dp[y][0]=S;
 88                                 else if(dp[y][1].f==-1&&dp[y][0].f!=S.f) dp[y][1]=S;
 89                         }
 90                         S=a[x][1];(S.f+=g[y])%=mod[k];S.pre=S.pos;S.pos=y;
 91                         if(!val||a[x][1].f!=-1)
 92                         {
 93                                 S.f+=a[x][0].f==-1;
 94                                 if(dp[y][0].f==-1) dp[y][0]=S;
 95                                 else if(dp[y][1].f==-1&&dp[y][0].f!=S.f) dp[y][1]=S;
 96                         }
 97                 }
 98                 x-=lowbit(x);
 99         }
100         return val;
101 }
102 void dfs(node x)
103 {
104         if(!x.pos) return;
105         vis[x.pos]=1;
106         if(dp[x.pre][0].f!=-1&&(dp[x.pre][0].f+g[x.pos])%mod[k]==x.f) dfs(dp[x.pre][0]);
107         else if(dp[x.pre][1].f!=-1&&(dp[x.pre][1].f+g[x.pos])%mod[k]==x.f) dfs(dp[x.pre][1]);
108 }
109 void add2(int x,int y,int z)
110 {
111         while(x<=n)
112         {
113                 if(c[x]<y)
114                 {
115                         c[x]=y;
116                         h[x]=z;
117                 }
118                 x+=lowbit(x);
119         }
120 }
121 int get2(int x,int &y)
122 {
123         int val=0,z=x;
124         while(x)
125         {
126                 val=max(val,c[x]);
127                 x-=lowbit(x);
128         }
129         while(z)
130         {
131                 if(val==c[z]) y=h[z];
132                 z-=lowbit(z);
133         }
134         return val;
135 }
136 void dfs2(int x)
137 {
138         if(!x) return;
139         dfs2(pre[x]);
140         printf("%lld ",x);
141 }
142 void solve()
143 {
144         printf("%lld
",R);
145         for(int i=1;i<=n;i++) if(vis[i]) printf("%lld ",i);
146         printf("
%lld
",L);
147         for(int i=1;i<=n;i++) c[i]=h[i]=0;
148         for(int i=1;i<=n;i++)
149         {
150                 if(vis[i]) continue;
151                 q[i]=get2(n-p[i],pre[i])+1;
152                 add2(n-p[i]+1,q[i],i);
153         }
154         for(int i=1;i<=n;i++)
155         {
156                 if(vis[i]) continue;
157                 if(q[i]==L)
158                 {
159                         dfs2(i);
160                         exit(0);
161                 }
162         }
163         exit(0);
164 }
165 signed main()
166 {
167         //freopen("sanrd9.in","r",stdin);
168         n=read();
169         for(int i=1;i<=n;i++) a[i][0].f=a[i][1].f=dp[i][0].f=dp[i][1].f=-1;
170         for(int i=1;i<=n;i++) p[i]=read();k=p[1]==471748;
171         for(int i=1;i<=n;i++) h[i]=c[i]=0;
172         for(int i=1,x;i<=n;i++)
173         {
174                 q[i]=x=get(f[0][i],n-p[i])+1;
175                 f[0][i]=max(f[0][i],1ll);
176                 add(n-p[i]+1,x,f[0][i]);
177                 L=max(L,x);
178         }
179         for(int i=1;i<=n;i++) if(q[i]==L) (al+=f[0][i])%=mod[k];
180         for(int i=1;i<=n;i++) h[i]=c[i]=0;
181         for(int i=n,x;i;i--)
182         {
183                 x=get(f[1][i],p[i]-1)+1;
184                 f[1][i]=max(f[1][i],1ll);
185                 if(x+q[i]-1==L) g[i]=f[0][i]*f[1][i]%mod[k];
186                 else g[i]=0;
187                 add(p[i],x,f[1][i]);
188         }
189         for(int i=1;i<=n;i++) h[i]=c[i]=0;
190         for(int i=1,x;i<=n;i++)
191         {
192                 q[i]=x=get1(p[i],i)+1;
193                 R=max(R,x);
194                 add1(p[i]+1,x,i);
195         }
196         for(int i=n;i;i--)
197         {
198                 if(q[i]==R)
199                 {
200                         if(dp[i][0].f!=-1&&dp[i][0].f<al) dfs(dp[i][0]),solve();
201                         if(dp[i][1].f!=-1&&dp[i][1].f<al) dfs(dp[i][1]),solve();
202                 }
203         }
204         puts("-1");
205         return 0;
206 }
T3
原文地址:https://www.cnblogs.com/AthosD/p/12188616.html