【CSP-S 2019模拟】题解
T1:
显然可以用之前有次模拟的方法,在转移出去的里面选方案最大的作为重儿子倍增
由于写太久了
根本没时间写
#include<bits/stdc++.h>
using namespace std;
#define cs const
#define pb push_back
#define bg begin
#define pii pair<int,int>
#define fi first
#define se second
#define ll long long
cs int RLEN=1<<20|1;
inline char gc(){
static char ibuf[RLEN],*ib,*ob;
(ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ib==ob)?EOF:*ib++;
}
#define gc getchar
inline int read(){
char ch=gc();
int res=0;bool f=1;
while(!isdigit(ch))f^=ch=='-',ch=gc();
while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
return f?res:-res;
}
inline ll readl(){
char ch=gc();
ll res=0;bool f=1;
while(!isdigit(ch))f^=ch=='-',ch=gc();
while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
return f?res:-res;
}
template<class tp>inline void chemx(tp &a,tp b){a<b?a=b:0;}
template<class tp>inline void chemn(tp &a,tp b){a>b?a=b:0;}
cs int mod=1e9+7;
inline int add(int a,int b){return (a+=b)>=mod?a-mod:a;}
inline int dec(int a,int b){a-=b;return a+(a>>31&mod);}
inline void Add(int &a,int b){a+=b,a>=mod?(a-=mod):0;}
inline void Dec(int &a,int b){a-=b,a+=a>>31&mod;}
inline int mul(int a,int b){static ll r;r=1ll*a*b;return r>=mod?(r%mod):r;}
inline void Mul(int &a,int b){static ll r;r=1ll*a*b,a=r>=mod?(r%mod):r;}
inline int ksm(int a,int b,int res=1){for(;b;b>>=1,Mul(a,a))(b&1)&&(Mul(res,a),1);return res;}
cs ll inf=1e18+5;
inline ll fix(ll a){
return a<inf?a:inf;
}
cs int N=50005,M=21,L=17;
ll f[N][M],vl[L][N][M],vr[L][N][M];
int v[L][N][M];
int nxt[L][N][M];
int pw[M],p[N][10];
char s[N],t[N];
int n,q,m,fail[N],tr[N][10];
inline void init(){
for(int i=0,j=2;j<=m;j++){
while(i&&s[i+1]!=s[j])i=fail[i];
if(s[i+1]==s[j])i++;
fail[j]=i;
}
for(int i=0;i<m;i++){
for(int c=0;c<=9;c++){
int p=i;
while(p&&s[p+1]!=c+'0')p=fail[p];
if(s[p+1]==c+'0')p++;
tr[i][c]=p;
}
}
for(int i=0;i<=9;i++)tr[m][i]=m;
for(int i=1;i<=n;i++){
if(t[i]=='?')for(int c=0;c<=9;c++)p[i][c]=1;
else for(int c=0;c<=9;c++)p[i][c]=(c+'0'==t[i]);
}
for(int i=1;i<m;i++)f[n+1][i]=0;f[n+1][m]=1;
for(int i=n;i;i--){
for(int j=0;j<=m;j++){
f[i][j]=0;
ll mx=-1,hs=-1;
for(int k=0;k<=9;k++)if(p[i][k]){
f[i][j]=fix(f[i][j]+f[i+1][tr[j][k]]);
if(f[i+1][tr[j][k]]>mx)mx=f[i+1][tr[j][k]],hs=k;
}
nxt[0][i][j]=tr[j][hs],v[0][i][j]=hs,vl[0][i][j]=0;
for(int k=0;k<hs;k++)if(p[i][k])vl[0][i][j]=fix(vl[0][i][j]+f[i+1][tr[j][k]]);
vr[0][i][j]=fix(vl[0][i][j]+f[i+1][tr[j][hs]]);
}
}
for(int k=1;k<=16;k++){
int l=1<<(k-1);
for(int i=1;i+(1<<k)<=n+1;i++)
for(int j=0;j<=m;j++){
int x=nxt[k-1][i][j];
nxt[k][i][j]=nxt[k-1][i+l][x];
v[k][i][j]=add(mul(v[k-1][i][j],pw[k-1]),v[k-1][i+l][x]);
vl[k][i][j]=fix(vl[k-1][i][j]+vl[k-1][i+l][x]);
vr[k][i][j]=fix(vl[k-1][i][j]+vr[k-1][i+l][x]);
}
}
}
inline int dfs(ll k){
if(k>f[1][0])return -1;
int p=1,c=0,res=0;
while(p<=n){
for(int i=16;~i;i--){
if(p+(1<<i)<=n+1&&vl[i][p][c]<k&&k<=vr[i][p][c]){
Mul(res,pw[i]),Add(res,v[i][p][c]);
k-=vl[i][p][c],c=nxt[i][p][c],p+=1<<i;
}
}
if(p>n)break;
for(int i=0;i<=9;i++){
if(k>f[p+1][tr[c][i]])k-=f[p+1][tr[c][i]];
else{
Mul(res,10),Add(res,i),p++,c=tr[c][i];break;
}
}
}
return res;
}
inline void solve(){
n=read(),q=read();
scanf("%s",s+1);
m=strlen(s+1);
scanf("%s",t+1);
init();
while(q--){
cout<<dfs(readl())<<'\n';
}
}
int main(){
#ifdef Stargazer
freopen("lx.in","r",stdin);
freopen("my.out","w",stdout);
#endif
pw[0]=10;
for(int i=1;i<L;i++)pw[i]=mul(pw[i-1],pw[i-1]);
int T=read();
while(T--)solve();
}
T2:
考虑对于每个大小维护纯色块个数
那么答案其实是
就是对于一个纯色块,不会继续递归
那么减去递归会增加的贡献即可
发现纯色块对于独立
维护中纯色子区间个数
乘起来就是答案
#include<bits/stdc++.h>
using namespace std;
#define cs const
#define pb push_back
#define bg begin
#define pii pair<int,int>
#define fi first
#define se second
#define ll long long
cs int RLEN=1<<20|1;
inline char gc(){
static char ibuf[RLEN],*ib,*ob;
(ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ib==ob)?EOF:*ib++;
}
inline int read(){
char ch=gc();
int res=0;bool f=1;
while(!isdigit(ch))f^=ch=='-',ch=gc();
while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
return f?res:-res;
}
template<class tp>inline void chemx(tp &a,tp b){a<b?a=b:0;}
template<class tp>inline void chemn(tp &a,tp b){a>b?a=b:0;}
cs int N=(1<<21)+15;
char xxx;
int n,q,lim;
struct Seg{
#define lc (u<<1)
#define rc ((u<<1)|1)
#define mid ((l+r)>>1)
int v[22],s[N<<2];
void build(int u,int l,int r,int dep){
if(l==r)return;
v[dep]++;
build(lc,l,mid,dep-1),build(rc,mid+1,r,dep-1);
}
void update(int u,int l,int r,int dep,int p){
if(l==r){s[u]^=1;return;}
if(p<=mid)update(lc,l,mid,dep-1,p);
else update(rc,mid+1,r,dep-1,p);
int pre=s[u];s[u]=s[lc]+s[rc];
if((pre==0&&s[u]==1)||(pre==r-l+1&&s[u]==r-l))v[dep]--;
if((pre==1&&s[u]==0)||(pre==r-l&&s[u]==r-l+1))v[dep]++;
}
#undef lc
#undef rc
#undef mid
}t1,t2;
char yyy;
int main(){
#ifdef Stargazer
freopen("lx.cpp","r",stdin);
#endif
n=read(),lim=(1<<n),q=read();
t1.build(1,1,lim,n);
t2.build(1,1,lim,n);
while(q--){
int op=read(),x=read();
if(op==0)t1.update(1,1,lim,n,x);
else t2.update(1,1,lim,n,x);
ll res=0;
for(int i=0;i<=n;i++)
res+=(1ll<<((n-i)*2))-4ll*t1.v[i]*t2.v[i];
cout<<res<<'\n';
}
}
T3:
正解用到了平面图的特殊性质
实际上我根本没看到那句话
而我这个可以对不是平面图的一样做
对于一边不断删去点,另一边的一定是不断加点
这样可以双指针暴力维护
然后要中间的点在同一个联通块
把中间点权值设为,看一棵树权值和是否为
于是乎需要维护一下虚子树的
还有个问题是虽然上下都是树
但是可能连一起出现环
所以还要维护一下一个环上最下面的边
如果上面要连时已经连通的时候要把环上最下面的一条边断开
于是还需要化边为点来维护一个
然后随便写写
反正我光写就写了一个多小时
还因为写错一个小地方爆零了
#include<bits/stdc++.h>
using namespace std;
#define cs const
#define pb push_back
#define bg begin
#define pii pair<int,int>
#define fi first
#define se second
#define ll long long
cs int RLEN=1<<20|1;
inline char gc(){
static char ibuf[RLEN],*ib,*ob;
(ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ib==ob)?EOF:*ib++;
}
inline int read(){
char ch=gc();
int res=0;bool f=1;
while(!isdigit(ch))f^=ch=='-',ch=gc();
while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
return f?res:-res;
}
template<class tp>inline void chemx(tp &a,tp b){a<b?a=b:0;}
template<class tp>inline void chemn(tp &a,tp b){a>b?a=b:0;}
cs int N=800005;
char xxx;
int n,m1,m2,tim[N];
vector<pii>e1[N],e2[N];
struct pt{
int x,y;
}p[N];
namespace Lct{
cs int M=800005;
int val[M],rev[M],s[M],c[M],mx[M],xs[M],tot,fa[M],son[M][2];
#define lc(u) son[u][0]
#define rc(u) son[u][1]
inline bool isrt(int u){
return !fa[u]||(rc(fa[u])!=u&&lc(fa[u])!=u);
}
inline bool isrc(int u){
return rc(fa[u])==u;
}
inline void pushup(int u){
s[u]=(u<=n)+xs[u];
mx[u]=c[u];
if(lc(u)){
s[u]+=s[lc(u)];
if(tim[mx[lc(u)]]>tim[mx[u]])mx[u]=mx[lc(u)];
}
if(rc(u)){
s[u]+=s[rc(u)];
if(tim[mx[rc(u)]]>tim[mx[u]])mx[u]=mx[rc(u)];
}
}
inline void pushnow(int u){
swap(lc(u),rc(u)),rev[u]^=1;
}
inline void pushdown(int u){
if(!rev[u])return;
if(lc(u))pushnow(lc(u));
if(rc(u))pushnow(rc(u));
rev[u]=0;
}
inline void rotate(int v){
int u=fa[v],z=fa[u];
int t=isrc(v);
if(!isrt(u))son[z][isrc(u)]=v;
fa[v]=z;
son[u][t]=son[v][t^1];
fa[son[v][t^1]]=u;
fa[u]=v,son[v][t^1]=u;
pushup(u),pushup(v);
}
int stk[N],top;
inline void splay(int u){
stk[top=1]=u;
for(int v=u;!isrt(v);v=fa[v])stk[++top]=fa[v];
for(int i=top;i;i--)pushdown(stk[i]);
while(!isrt(u)){
if(!isrt(fa[u]))
isrc(u)==isrc(fa[u])?rotate(fa[u]):rotate(u);
rotate(u);
}
pushup(u);
}
inline void access(int u){
for(int v=0;u;v=u,u=fa[u]){
splay(u);
if(rc(u))xs[u]+=s[rc(u)];
if(v)xs[u]-=s[v],fa[v]=u;
rc(u)=v,pushup(u);
}
}
inline int findrt(int u){
access(u),splay(u);
while(pushdown(u),lc(u))u=lc(u);
splay(u);return u;
}
inline void makert(int u){
access(u),splay(u),pushnow(u);
}
inline void link(int u,int v){
access(u),splay(u),makert(v),fa[v]=u,xs[u]+=s[v];
pushup(u);
}
inline void cut(int u,int v){
makert(u),access(v),splay(v);
fa[lc(v)]=0,lc(v)=0,pushup(u),pushup(v);
}
inline int querysize(int u){
access(u),splay(u);return s[u];
}
inline int querypos(int u,int v){
makert(u),access(v),splay(v);
return mx[v];
}
}
using namespace Lct;
int a[N],b[N],cnt1,cnt2;
int pos1[N],pos2[N],pe1[N],pe2[N];
vector<int>p1[N],p2[N];
pii E1[N],E2[N];
ll sum[N];
inline ll gcd(ll a,ll b){
return b?gcd(b,a%b):a;
}
inline void cutedge(int id){
int u=E2[id].fi,v=E2[id].se;
if(findrt(u)==findrt(pe2[id])){
cut(u,pe2[id]);
}
if(findrt(v)==findrt(pe2[id])){
cut(v,pe2[id]);
}
}
inline void deletnode(int u){
for(int i=0;i<e2[u].size();i++){
int id=e2[u][i].se;
cutedge(id);
}
}
inline void insertnode(int u){
for(int i=0;i<e1[u].size();i++){
int v=e1[u][i].fi,id=e1[u][i].se;
if(findrt(u)==findrt(v)){
int pos=querypos(u,v);
cutedge(pos);
}
link(v,pe1[id]),link(u,pe1[id]);
}
}
char yyy;
int main(){
#ifdef Stargazer
freopen("lx.in","r",stdin);
#endif
n=read(),m1=read(),m2=read();
for(int i=1;i<=n;i++)val[++tot]=1,pushup(tot);
for(int i=1;i<=m1;i++)pos1[i]=++tot;
for(int i=1;i<n+m1;i++)pe1[i]=++tot;
for(int i=1;i<=m1;i++){
p[i].x=read(),p[i].y=read();
a[i]=p[i].y;
}
sort(a+1,a+m1+1);
cnt1=unique(a+1,a+m1+1)-a-1;
for(int i=1;i<=m1;i++){
p[i].y=lower_bound(a+1,a+cnt1+1,p[i].y)-a;
p1[p[i].y].pb(pos1[i]);
}
for(int i=cnt1;i;i--)sum[i]=sum[i+1]+(ll)p1[i].size();
for(int i=1;i<n+m1;i++){
int op=read(),v=read(),u=read();
if(op==2){
if(p[u].y<p[v].y)swap(u,v);
v=pos1[v];
}
u=pos1[u];
e1[u].pb(pii(v,i));
E1[i]=pii(u,v);
}
for(int i=1;i<=m2;i++){
p[i].x=read(),p[i].y=-read();
a[i]=p[i].y;
}
for(int i=1;i<=m2;i++)pos2[i]=++tot;
for(int i=1;i<n+m2;i++)pe2[i]=++tot;
sort(a+1,a+m2+1);
cnt2=unique(a+1,a+m2+1)-a-1;
for(int i=1;i<=m2;i++){
p[i].y=lower_bound(a+1,a+cnt2+1,p[i].y)-a;
p2[p[i].y].pb(pos2[i]);
}
for(int i=1;i<n+m2;i++){
int op=read(),v=read(),u=read();
if(op==2&&p[u].y<p[v].y)swap(u,v);
tim[i]=p[u].y;
c[pe2[i]]=i;pushup(pe2[i]);
u=pos2[u];if(op==2)v=pos2[v];
E2[i]=pii(u,v);
if(op==1){
link(u,pe2[i]),link(v,pe2[i]);
}
else {
link(u,pe2[i]),link(v,pe2[i]);
}
e2[u].pb(pii(v,i));
}
ll res=0;
for(int i=cnt2,j=1;i;i--){
for(int t=0;t<p2[i].size();t++){
int u=p2[i][t];
deletnode(u);
}
while(querysize(1)<n&&j<=cnt1){
for(int t=0;t<p1[j].size();t++){
int u=p1[j][t];
insertnode(u);
}
j++;
}
res+=1ll*p2[i].size()*sum[j];
}
ll all=1ll*m2*m1;
ll g=gcd(all,res);
all/=g,res/=g;
if(!res)puts("0");
else if(all==res)puts("1");
else cout<<res<<"/"<<all<<'\n';
return 0;
}