3.22 模拟赛

T1 sort

题目大意:

$n$个人,每个人有一个分,$m$对关系,表示两个人的分数关系,已知关系中每个人最多有一个人的分比他小

求满足条件的所有人的排名有多少种

思路:

容易发现若没有$=$号则使用组合数就可以非常简单的合并子树

若有两个等级数为$i,j$ 我们可以枚举最终的等级数$k$,设这样的方案数为$d(i,j,k)$ 则$dp[u][k]+=dp[x][i]*dp[v][j]*d(i,j,k)$

在dp之前 我们预处理$d$数组就可以使复杂度满足

 1 #include<bits/stdc++.h>
 2 #define ll long long
 3 #define ull unsigned long long
 4 #define db double
 5 #define inf 2139092143
 6 #define MAXN 510
 7 #define MOD 998244353
 8 #define rep(i,s,t) for(register int i=(s),i##end=(t);i<=i##end;++i)
 9 #define dwn(i,s,t) for(register int i=(s),i##end=(t);i>=i##end;--i)
10 #define ren for(int i=fst[x];i;i=nxt[i])
11 #define pls(a,b) (a+b)%MOD
12 #define mns(a,b) (a-b+MOD)%MOD
13 #define mul(a,b) (1LL*a*b)%MOD
14 using namespace std;
15 inline int read()
16 {
17     int x=0,f=1;char ch=getchar();
18     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
19     while(isdigit(ch)) {x=x*10+ch-'0',ch=getchar();}
20     return x*f;
21 }
22 int n,m,fst[MAXN],nxt[MAXN<<1],to[MAXN<<1],cnt,vis[MAXN],fa[MAXN];
23 int d[MAXN][MAXN][MAXN],f[MAXN][MAXN],t[MAXN][MAXN],ind[MAXN],sz[MAXN];
24 struct opt{int u,v,t;}q[MAXN];
25 int find(int x) {return x==fa[x]?x:fa[x]=find(fa[x]);}
26 void add(int u,int v) {nxt[++cnt]=fst[u],fst[u]=cnt,to[cnt]=v,ind[v]++;}
27 void pe(int &a,int b) {a=pls(a,b);}
28 int dfs(int x)
29 {
30     if(vis[x]<0) return 0;vis[x]=-1;
31     ren if(!vis[to[i]]&&!dfs(to[i])) return 0;else if(vis[to[i]]<0) return 0;
32     vis[x]=1;return 1;
33 }
34 void dp(int x)
35 {
36     f[x][1]=sz[x]=1;ren if(to[i]!=x)
37     {
38         dp(to[i]);rep(j,1,sz[x]) rep(k,1,sz[to[i]]) rep(o,max(j,k),j+k)
39             pe(t[x][o],mul(mul(f[x][j],f[to[i]][k]),d[j-1][k][o-1]));
40         sz[x]+=sz[to[i]];rep(i,1,sz[x]) f[x][i]=t[x][i],t[x][i]=0;
41     }
42 }
43 int main()
44 {
45     freopen("sort.in","r",stdin);
46     freopen("sort.out","w",stdout);
47     n=read(),m=read();char ch[2];rep(i,1,n) fa[i]=i;rep(i,1,m)
48     {
49         scanf("%d%s%d",&q[i].u,ch,&q[i].v);
50         if(ch[0]=='=') fa[find(q[i].u)]=find(q[i].v),q[i].t=1;
51     }
52     rep(i,1,m) if(!q[i].t) add(find(q[i].u),find(q[i].v));
53     rep(i,1,n) if(!vis[find(i)]&&!dfs(find(i))) {puts("0");return 0;}
54     d[0][0][0]=1;rep(i,0,n) rep(j,0,n) rep(k,max(i,j),min(i+j,n)) if(i|j)
55     {
56         if(i) pe(d[i][j][k],d[i-1][j][k-1]);if(j) pe(d[i][j][k],d[i][j-1][k-1]);
57         if(i*j) pe(d[i][j][k],d[i-1][j-1][k-1]);
58     }
59     rep(i,1,n) if(!ind[find(i)]) add(n+1,find(i));dp(n+1);int ans=0;
60     rep(i,1,n+1) ans=pls(ans,f[n+1][i]);printf("%d
",ans);
61 }
View Code

T2 mission

题解链接

考场的$dsu space on space tree$被卡掉了,写一波主席树合并

 1 #include<bits/stdc++.h>
 2 #define ll long long
 3 #define db double
 4 #define inf 2139092143
 5 #define MAXN 10100
 6 #define DMAXN 640100
 7 #define DMAXM 1280100
 8 #define MOD 998244353
 9 #define rep(i,s,t) for(register int i=(s),i##end=(t);i<=i##end;++i)
10 #define dwn(i,s,t) for(register int i=(s),i##end=(t);i>=i##end;--i)
11 #define ren for(int i=fst[x];i;i=nxt[i])
12 #define pls(a,b) (a+b)%MOD
13 #define mns(a,b) (a-b+MOD)%MOD
14 #define mul(a,b) (1LL*a*b)%MOD
15 #define ist(u,v,w) D::ins(u,v,w)
16 using namespace std;
17 inline int read()
18 {
19     int x=0,f=1;char ch=getchar();
20     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
21     while(isdigit(ch)) {x=x*10+ch-'0',ch=getchar();}
22     return x*f;
23 }
24 int n,m,fst[MAXN],nxt[MAXN<<1],to[MAXN<<1],cnt,val[MAXN],fa[MAXN];
25 int tot,ls[MAXN<<6],rs[MAXN<<6],ss,tt,rt[MAXN];
26 namespace D
27 {
28     int S,T,fst[DMAXN],nxt[DMAXM<<1],to[DMAXM<<1],val[DMAXM<<1],cnt;
29     int cur[DMAXN],vis[DMAXN],dis[DMAXN],q[DMAXN],l,r,tot;
30     void mem(){memset(fst,0,sizeof(fst));cnt=1;}
31     void add(int u,int v,int w){nxt[++cnt]=fst[u],fst[u]=cnt,to[cnt]=v,val[cnt]=w;}
32     void ins(int u,int v,int w){add(u,v,w);add(v,u,0);}
33     int bfs()
34     {
35         vis[T]=++tot,dis[T]=0,q[l=r=1]=T;int x;
36         while(l<=r)
37         {
38             x=q[l++];cur[x]=fst[x];ren if(vis[to[i]]!=tot&&val[i^1])
39                 vis[to[i]]=tot,dis[to[i]]=dis[x]+1,q[++r]=to[i];
40         }
41         return vis[S]==tot;
42     }
43     int dfs(int x,int a)
44     {
45         if(x==T||!a) return a;int flw=0,f;
46         for(int& i=cur[x];i&&a;i=nxt[i])
47             if(val[i]&&dis[to[i]]==dis[x]-1&&(f=dfs(to[i],min(a,val[i]))))
48                 val[i]-=f,val[i^1]+=f,a-=f,flw+=f;
49         return flw;
50     }
51     int solve(int s,int t,int ans=0)
52     {
53         S=s,T=t;int f;while(bfs()) ans+=dfs(S,inf);
54         return ans;
55     }
56 };
57 void add(int u,int v){nxt[++cnt]=fst[u],fst[u]=cnt,to[cnt]=v;}
58 void mdf(int &k,int kk,int l,int r,int x)
59 {
60     k=++tot;if(l==r) {ist(k+n,x,inf);return ;}int mid=l+r>>1;
61     if(val[x]<=mid) rs[k]=rs[kk],mdf(ls[k],ls[kk],l,mid,x);
62     else ls[k]=ls[kk],mdf(rs[k],rs[kk],mid+1,r,x);
63 }
64 void query(int k,int l,int r,int a,int b,int x)
65 {
66     if(!k) return ;if(l==a&&r==b) {ist(tot+n,k+n,x);return ;}int mid=l+r>>1;
67     if(b<=mid) query(ls[k],l,mid,a,b,x);else if(a>mid) query(rs[k],mid+1,r,a,b,x);
68     else {query(ls[k],l,mid,a,mid,x);query(rs[k],mid+1,r,mid+1,b,x);}
69 }
70 int merge(int x,int y,int l,int r)
71 {
72     if(!(x*y)) return x|y;int z=++tot,mid=l+r>>1;
73     if(l==r) {ist(z+n,x+n,inf);ist(z+n,y+n,inf);}
74     ls[z]=merge(ls[x],ls[y],l,mid);rs[z]=merge(rs[x],rs[y],mid+1,r);return z;
75 }
76 void dfs(int x){mdf(rt[x],rt[x],1,n,x);ren dfs(to[i]),rt[x]=merge(rt[x],rt[to[i]],1,n);}
77 int main()
78 {
79     freopen("mission.in","r",stdin);
80     freopen("mission.out","w",stdout);
81     n=read(),m=read();rep(i,2,n) fa[i]=read(),add(fa[i],i);rep(i,1,n) val[i]=read();
82     D::mem();dfs(1);ss=0;int x,a,b,t,k;
83     rep(i,1,tot) {if(ls[i]) ist(i+n,ls[i]+n,inf);if(rs[i]) ist(i+n,rs[i]+n,inf);}
84     while(m--)
85         {x=++tot,a=read(),b=read(),k=read(),t=read();ist(ss,x+n,t);query(rt[k],1,n,a,b,t);}
86     tt=n+tot+1;rep(i,1,n) ist(i,tt,1);
87     printf("%d
",D::solve(ss,tt));
88 }
View Code

T3 path

题目大意:

一棵树,给出$m$条路径,求选出两个路径使其中一个被另一个完全包含的概率

思路:

考虑一个路径$asim b$被另一条路径所包含的情况,

若$a==b$ 则另一个路径的两端点需要分别在子树内和子树外

若$a$为$b$的祖先,则另一个路径的两端点需要在$b$的子树内,$a$在$asim b$上的儿子的子树外

若$a,b$互不为祖先,则分别在$a,b$的子树内

将两个值同时在两个区间里的限制条件转换成一个二维点在矩形里的条件

然后扫描线树状数组二维数点查询每个点在哪几个矩形里即可

 1 #include<bits/stdc++.h>
 2 #define ll long long
 3 #define db double
 4 #define inf 2139092143
 5 #define MAXN 530100
 6 #define MOD 998244353
 7 #define rep(i,s,t) for(register int i=(s),i##end=(t);i<=i##end;++i)
 8 #define dwn(i,s,t) for(register int i=(s),i##end=(t);i>=i##end;--i)
 9 #define ren for(int i=fst[x];i;i=nxt[i])
10 #define pls(a,b) (a+b)%MOD
11 #define mns(a,b) (a-b+MOD)%MOD
12 #define mul(a,b) (1LL*a*b)%MOD
13 using namespace std;
14 inline int read()
15 {
16     int x=0,f=1;char ch=getchar();
17     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
18     while(isdigit(ch)) {x=x*10+ch-'0',ch=getchar();}
19     return x*f;
20 }
21 int n,m,fst[MAXN],nxt[MAXN<<1],to[MAXN<<1],cnt,dep[MAXN];
22 int f[21][MAXN],in[MAXN],ou[MAXN],tot,c[MAXN];ll ans;
23 void mdf(int x,int val) {for(;x<=n;x+=x&-x) c[x]+=val;}
24 int query(int x,int res=0) {for(;x;x-=x&-x) res+=c[x];return res;}
25 struct pnt{int x,y;}p[MAXN];struct seg{int x,l,r,w;}g[MAXN<<2];
26 bool operator < (const pnt &a,const pnt &b) {return a.x<b.x;}
27 bool operator == (const pnt &a,const pnt &b) {return a.x==b.x&&a.y==b.y;}
28 bool operator < (const seg &a,const seg &b) {return a.x<b.x;}
29 void add(int u,int v){nxt[++cnt]=fst[u],fst[u]=cnt,to[cnt]=v;}
30 void dfs(int x)
31 {
32     in[x]=++tot;rep(j,1,20) f[j][x]=f[j-1][f[j-1][x]];
33     ren if(to[i]^f[0][x]) f[0][to[i]]=x,dep[to[i]]=dep[x]+1,dfs(to[i]);ou[x]=tot;
34 }
35 int anc(int x,int k){rep(i,0,20) if((1<<i)&k) x=f[i][x];return x;}
36 void ivt(int x,int y,int l,int r)
37 {
38     if(l>r||x>y) return ;if(x>l) swap(x,l),swap(y,r);
39     g[++tot]=(seg){x,l,r,1},g[++tot]=(seg){y+1,l,r,-1};
40 }
41 ll gcd(ll a,ll b){return !b?a:gcd(b,a%b);}
42 int main()
43 {
44     freopen("path.in","r",stdin);
45     freopen("path.out","w",stdout);
46     n=read(),m=read();int a,b;rep(i,2,n) a=read(),b=read(),add(a,b),add(b,a);
47     f[0][1]=1;dfs(1);tot=0;rep(i,1,m)
48     {
49         a=read(),b=read();p[i]=(pnt){min(in[a],in[b]),max(in[a],in[b])};
50         if(dep[b]>dep[a]) swap(a,b);
51         if(a==b) ivt(in[a],ou[a],1,in[a]),ivt(in[a],ou[a],ou[a]+1,n);
52         if(in[b]<=in[a]&&in[a]<=ou[b])
53         {
54             b=anc(a,dep[a]-dep[b]-1);
55             ivt(in[a],ou[a],1,in[b]-1),ivt(in[a],ou[a],ou[b]+1,n);
56         }
57         else ivt(in[a],ou[a],in[b],ou[b]);
58     }
59     sort(p+1,p+m+1);sort(g+1,g+tot+1);int pos=1;
60     rep(i,1,m)
61     {
62         for(;pos<=tot&&g[pos].x<=p[i].x;pos++) mdf(g[pos].l,g[pos].w),mdf(g[pos].r+1,-g[pos].w);
63         ans+=query(p[i].y);
64     }
65     pos=1;rep(i,1,m) {for(;pos<=m&&p[i]==p[pos];pos++);ans-=1LL*(pos-i)*(pos-i-1)>>1;i=pos-1;}
66     ans-=m;printf("%.6lf",2.0*ans/m/(m-1));
67 }
View Code
原文地址:https://www.cnblogs.com/yyc-jack-0920/p/10583184.html