省选模拟六 题解
写在前面:
考试不在状态
码题的时候根本不知道自己在码什么
$T2$转移写少暴露出对$SAM$理解不深刻
不
根本没有理解
感觉吃枣药丸
A. Yist
标签:
根号思想
题解:
不难发现式子其实是个等比数列求和
直接模拟显然会被菊花图卡
考虑对于每个点按度数是否大于$\sqrt{n}$分为重点和轻点
对于每个点$x$维护$g[x]$代表周围所以轻点的贡献和
每次轻点更改时暴力把周围的$g$更新
对于重点在操作$x$时暴力统计即可
复杂度$O(n\sqrt{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\n",(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 }
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\n",dfs(0,1)); 77 return 0; 78 }
C. Sanrd
标签:
$BIT$的神仙题
题解:
一道$BIT$题打了200行+
可怕~
但这题的思路很棒
首先$LIS$和$LDS$的重复部分最多为$1$
考虑求出经过每个点的$LDS$个数$g[i]$
设
$$all=\sum\limits_{i=1}^{n}g[i]$$
那么一个$LIS$集合${a_1,a_2...a_k}$
设
$$val=\sum\limits_{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\n",R); 145 for(int i=1;i<=n;i++) if(vis[i]) printf("%lld ",i); 146 printf("\n%lld\n",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 }