3.15 模拟赛

T1 1e5只龙的故事

题目大意:

一棵树 q次询问 每次询问一条路径上的第$k$小的点的权值(不去重),然后把整个路径上所有点的权值都改成这个值

思路:

好暴力啊

使用树剖线段树暴力维护权值一样的区间 查询的时候开个数组记录所有满足条件的区间 排序后直接查即可

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cstdlib>
 5 #include<cmath>
 6 #include<algorithm>
 7 #include<queue>
 8 #include<vector>
 9 #include<map>
10 #include<set>
11 #define ll long long
12 #define db double
13 #define inf 2139062143
14 #define MAXN 180100
15 #define rep(i,s,t) for(register int i=(s),i##__end=(t);i<=i##__end;++i)
16 #define dwn(i,s,t) for(register int i=(s),i##__end=(t);i>=i##__end;--i)
17 #define ren for(register int i=fst[x];i;i=nxt[i])
18 #define pb(i,x) vec[i].push_back(x)
19 #define pls(a,b) (a+b)%MOD
20 #define mns(a,b) (a-b+MOD)%MOD
21 #define mul(a,b) (1LL*(a)*(b))%MOD
22 using namespace std;
23 inline int read()
24 {
25     int x=0,f=1;char ch=getchar();
26     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
27     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
28     return x*f;
29 }
30 int n,nxt[MAXN<<1],fst[MAXN],to[MAXN<<1],cnt,val[MAXN],tag[MAXN<<2];
31 int sz[MAXN],dep[MAXN],fa[MAXN],hvs[MAXN],bl[MAXN],in[MAXN],tot;
32 void add(int u,int v) {nxt[++cnt]=fst[u],fst[u]=cnt,to[cnt]=v;}
33 void dfs(int x,int pa)
34 {
35     sz[x]=1,fa[x]=pa;ren if(to[i]^pa) 
36         {dep[to[i]]=dep[x]+1;dfs(to[i],x);sz[x]+=sz[to[i]],hvs[x]=sz[to[i]]>sz[hvs[x]]?to[i]:hvs[x];}
37 }
38 void Dfs(int x,int anc)
39 {
40     bl[x]=anc,in[x]=++tot;if(!hvs[x]) return ;Dfs(hvs[x],anc);
41     ren if(to[i]^fa[x]&&to[i]^hvs[x]) Dfs(to[i],to[i]);
42 }
43 struct ask{int x,v;}res[MAXN];int top;
44 void pshd(int k) {if(tag[k]) tag[k<<1]=tag[k<<1|1]=tag[k],tag[k]=0;}
45 void mdf(int k,int l,int r,int a,int b,int x)
46 {
47     if(l==a&&r==b) {tag[k]=x;return ;}int mid=l+r>>1;pshd(k);
48     if(b<=mid) mdf(k<<1,l,mid,a,b,x);else if(a>mid) mdf(k<<1|1,mid+1,r,a,b,x);
49     else {mdf(k<<1,l,mid,a,mid,x);mdf(k<<1|1,mid+1,r,mid+1,b,x);}
50 }
51 void query(int k,int l,int r,int a,int b)
52 {
53     if(l==a&&r==b&&tag[k]) {res[++top]=(ask){tag[k],r-l+1};return ;}int mid=l+r>>1;pshd(k);
54     if(b<=mid) query(k<<1,l,mid,a,b);else if(a>mid) query(k<<1|1,mid+1,r,a,b);
55     else {query(k<<1,l,mid,a,mid);query(k<<1|1,mid+1,r,mid+1,b);}
56 }
57 bool cmp(ask a,ask b){return a.x<b.x;}
58 int Query(int a,int b,int k)
59 {
60     for(top=0;bl[a]!=bl[b];a=fa[bl[a]])
61         {if(dep[bl[a]]<dep[bl[b]]) swap(a,b);query(1,1,n,in[bl[a]],in[a]);}
62     if(in[a]>in[b]) swap(a,b);query(1,1,n,in[a],in[b]);
63     sort(res+1,res+top+1,cmp);int sum=0;rep(i,1,top) {sum+=res[i].v;if(sum>=k) return res[i].x;}
64 }
65 void work(int a,int b,int k)
66 {
67     for(;bl[a]!=bl[b];a=fa[bl[a]])
68         {if(dep[bl[a]]<dep[bl[b]]) swap(a,b);mdf(1,1,n,in[bl[a]],in[a],k);}
69     if(in[a]>in[b]) swap(a,b);mdf(1,1,n,in[a],in[b],k);
70 }
71 int main()
72 {
73     n=read();int a,b,x=read(),y=read(),MOD=read();
74     rep(i,1,n) val[i]=read();rep(i,2,n) a=read(),b=read(),add(a,b),add(b,a);
75     int q=read(),k;dfs(1,0);Dfs(1,1);rep(i,1,n) mdf(1,1,n,in[i],in[i],val[i]);
76     while(q--)
77         {a=read(),b=read(),k=read();k=Query(a,b,k);printf("%d\n",k);work(a,b,pls(mul(k,x),y)+1);}
78 }
View Code

 

T2 小R的箱子

题目大意:

每个箱子有长$x$和宽$y$,只有满足$a.x<=b.x$且$a.y<=b.y$才能把$a$装进$b$内(不能交换x y

且每个箱子里只能装一个,但是可以嵌套。

思路:

每个箱子向可以装它的箱子连边,费用为起点箱子的面积

把每个点拆成两个点,分别与$S$,$T$连边来限制流量,跑一个最大费用流

用总费用去减即可

这样就需要去重,所有相等的看做一个,其余的直接装进去(否则两个相等的会互相装

(原来一直以来我的费用流都是假的,自闭了

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cstdlib>
 5 #include<cmath>
 6 #include<algorithm>
 7 #include<queue>
 8 #include<vector>
 9 #include<map>
10 #include<set>
11 #define ll long long
12 #define db double
13 #define inf 2139062143
14 #define MAXN 510
15 #define MAXM 40100
16 #define rep(i,s,t) for(register int i=(s),i##__end=(t);i<=i##__end;++i)
17 #define dwn(i,s,t) for(register int i=(s),i##__end=(t);i>=i##__end;--i)
18 #define ren for(register int i=fst[x];i;i=nxt[i])
19 #define pb(i,x) vec[i].push_back(x)
20 #define pls(a,b) (a+b)%MOD
21 #define mns(a,b) (a-b+MOD)%MOD
22 #define mul(a,b) (1LL*(a)*(b))%MOD
23 using namespace std;
24 inline int read()
25 {
26     int x=0,f=1;char ch=getchar();
27     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
28     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
29     return x*f;
30 }
31 int n,x[MAXN],y[MAXN],S,T,ban[MAXN];
32 struct ZKW
33 {
34     int fst[MAXN],to[MAXM<<1],nxt[MAXM<<1],val[MAXM<<1],cos[MAXM<<1],cnt;
35     int dis[MAXN],vis[MAXN],res;
36     ZKW() {res=0,cnt=1;memset(fst,0,sizeof(fst));}
37     void add(int u,int v,int w,int c) {nxt[++cnt]=fst[u],fst[u]=cnt,to[cnt]=v,val[cnt]=w,cos[cnt]=c;}
38     void ins(int u,int v,int w,int c) {add(u,v,w,c);add(v,u,0,-c);}
39     int spfa()
40     {
41         memset(dis,127,sizeof(dis));
42         queue<int> q;
43         dis[T]=0,vis[T]=1;q.push(T);
44         while(!q.empty())
45         {
46             int x=q.front();q.pop();vis[x]=0;
47             for(int i=fst[x];i;i=nxt[i])
48                 if(val[i^1]&&dis[to[i]]>dis[x]-cos[i])
49                 {
50                     dis[to[i]]=dis[x]-cos[i];
51                     if(!vis[to[i]]) {q.push(to[i]);vis[to[i]]=1;}
52                 }
53         }
54         return dis[S]!=inf;
55     }
56     int dfs(int x,int a)
57     {
58         if(x==T||!a) {res+=dis[S]*a;return a;}
59         if(vis[x])return 0;
60         vis[x]=1;
61         int res=0,f;
62         for(int i=fst[x];i&&a;i=nxt[i])
63             if(val[i]&&dis[to[i]]==dis[x]-cos[i]&&(f=dfs(to[i],min(a,val[i]))))
64                 res+=f,val[i]-=f,val[i^1]+=f,a-=f;
65         return res;
66     }
67     void solve(int flw=0) 
68     {
69         int f;while(spfa()) 
70             do{memset(vis,0,sizeof(vis));f=dfs(S,inf),flw+=f;}while(f);
71     }
72 }Z;
73 int main()
74 {
75     n=read();rep(i,1,n) x[i]=read(),y[i]=read();S=(n<<1)+10,T=S+1;int sum=0;
76     rep(i,1,n) rep(j,i+1,n) if(x[i]==x[j]&&y[i]==y[j]) ban[max(j,i)]=1;
77     rep(i,1,n) rep(j,1,n) if(i!=j&&x[i]<=x[j]&&y[i]<=y[j]&&ban[i]==0&&ban[j]==0) Z.ins(i,j+n,1,-x[i]*y[i]);
78     rep(i,1,n) if(!ban[i]) Z.ins(S,i,1,0),Z.ins(i+n,T,1,0),sum+=x[i]*y[i];
79     Z.solve();
80     printf("%d\n",sum+Z.res);
81 }
View Code

 

T3 绯红之王

题目大意:

已知数列$a$,求$\sum\limits_{i=1}^n {a_i}^k$

思路:

很久以前讲过的题,调了一年才搞出来

首先设$f_k=\sum\limits_{i=1}^n {a_i}^k$ , $g_k$表示对于所有$C_n^k$种选择的方法,$g_k=$所有方法内各个数相乘的和

例如数列中有四个数$a,b,c,d$ 则

$g_0=1$

$g_1=a+b+c+d$

$g_2=ab+ac+ad+bc+bd+cd$

$g_3=abc+abd+acd+bcd,g_4=abcd$

我们可以发现

$f_2=f_1 * g_1 - 2g_2$

$f_3=f_2 * g_1 - f_1* g_2 + 3g_3$

$f_4=f_3*g_1-f_2*g_2+f_1*g_3-4g_4$

发现下标为偶数的$g$都变成了其相反数,而且这是一个$f_0$在变化的分治$NTT$形式

那么我们将$f_0$设为0,在$cdq$到$l==r$时,再加上这个$n*g_n$贡献

现在考虑如何计算$g$数组,因为$g_i$是齐次轮换对称式 可以通过计算两部分再合并

例如$h_0=1,h_1=a+b+c,h_2=ab+ac+bc,h_3=abc$

$t_0=1,t_1=d+e+f,t_2=de+df+ed,t_3=def$

则$g_0=h_0*t_0=1$

$g_1=h_0*t_1+h_1*t_0$

$g_2=h_0*t_2+h_1*t_1+h_2*t_0$

$......$

这样可以维护一个类似线段树的结构来计算$g$,即一开始每个点有一个自己的多项式$1,a_i$

然后一层一层往上合并,计算出$g$后再用分治$NTT$来计算$f$

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cstdlib>
 5 #include<cmath>
 6 #include<algorithm>
 7 #include<queue>
 8 #include<vector>
 9 #include<map>
10 #include<set>
11 #define ll long long
12 #define db double
13 #define inf 2139062143
14 #define MAXN 800100
15 #define MOD 998244353
16 #define rep(i,s,t) for(register int i=(s),i##__end=(t);i<=i##__end;++i)
17 #define dwn(i,s,t) for(register int i=(s),i##__end=(t);i>=i##__end;--i)
18 #define ren for(register int i=fst[x];i;i=nxt[i])
19 #define pb(i,x) vec[i].push_back(x)
20 #define pls(a,b) (1LL*a%MOD+b%MOD+MOD)%MOD
21 #define mns(a,b) (1LL*a%MOD-b%MOD+MOD)%MOD
22 #define mul(a,b) ((ll)(1LL*(a))%MOD*(b)%MOD)%MOD
23 using namespace std;
24 inline int read()
25 {
26     int x=0,f=1;char ch=getchar();
27     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
28     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
29     return x*f;
30 }
31 int n,rev[MAXN],l2[MAXN],pw[MAXN],A[MAXN],B[MAXN],aa[MAXN];
32 int g[MAXN],f[MAXN];
33 vector<int> vec[MAXN];
34 int q_pow(int bas,int t,int res=1)
35 {
36     for(;t;bas=mul(bas,bas),t>>=1)
37         if(t&1) res=mul(res,bas);return res;
38 }
39 void ntt(int *a,int n,int f)
40 {
41     rep(i,0,n-1) if(i<rev[i]) swap(a[i],a[rev[i]]);
42     for(int i=1;i<n;i<<=1)
43     {
44         int wn=pw[i<<1];if(f==-1) wn=q_pow(wn,MOD-2);
45         for(int j=0;j<n;j+=i<<1)
46         {
47             int w=1,x,y;
48             for(int k=0;k<i;k++,w=mul(w,wn))
49                 x=a[k+j],y=mul(a[i+j+k],w),a[j+k]=pls(x,y),a[i+j+k]=mns(x,y);
50         }
51     }
52     if(f==1) return ;int nv=q_pow(n,MOD-2);
53     rep(i,0,n-1) a[i]=mul(a[i],nv);
54 }
55 void solve(int *a,int *b,int lmt)
56 {
57     ntt(a,lmt,1);ntt(b,lmt,1);rep(i,0,lmt-1) a[i]=mul(a[i],b[i]);
58     ntt(a,lmt,-1);
59 }
60 void Div(int l,int r,ll lmt=0)
61 {
62     if(l==r) return ;int mid=(l+r)>>1,lg;
63     Div(l,mid);Div(mid+1,r);lg=l2[r-l+1]+1,lmt=1<<lg;
64     rep(i,0,lmt-1) rev[i]=(rev[i>>1]>>1)|((i&1)<<(lg-1)),A[i]=B[i]=0;
65     rep(i,0,vec[l].size()-1) A[i]=vec[l][i];
66     rep(i,0,vec[mid+1].size()-1) B[i]=vec[mid+1][i];
67     solve(A,B,lmt);
68     vec[l].clear();vec[mid+1].clear();
69     rep(i,0,lmt-1) vec[l].push_back(A[i]);
70 }
71 void cdq(int l,int r)
72 {
73     if(l==r) {f[l]=pls(f[l],mul(g[l],l));return ;}
74     int mid=l+r>>1,lmt=r-l+1;cdq(l,mid);
75     int t=l2[lmt]+1;lmt=1<<t;
76     rep(i,0,lmt-1) rev[i]=(rev[i>>1]>>1)|((i&1)<<(t-1)),A[i]=B[i]=0;
77     rep(i,l,mid) A[i-l]=f[i];rep(i,1,r-l) B[i-1]=g[i];
78     solve(A,B,lmt);rep(i,mid+1,r) f[i]=pls(f[i],A[i-l-1]);
79     cdq(mid+1,r);
80 }
81 int main()
82 {
83     n=read();rep(i,1,n) aa[i]=read();rep(i,2,n<<1) l2[i]=l2[i>>1]+1;
84     rep(i,1,n<<1) pw[i]=q_pow(3,(MOD-1)/i);
85     rep(i,1,n) vec[i].push_back(1),vec[i].push_back(aa[i]);
86     Div(1,n);rep(i,0,n) g[i]=vec[1][i];
87     rep(i,0,n) if(!(i&1)) g[i]=-g[i];
88     cdq(0,n);rep(i,1,n) printf("%d\n",f[i]);
89 }
View Code

 

posted @ 2019-03-16 08:31  jack_yyc  阅读(177)  评论(0编辑  收藏  举报