来中山纪中半个月了,差不多就要结束了,
写一些之前考试能更正的题解吧,还有一些不是给人做的(比如IOI2018互测。。
备注:我不会的就没有放上来了,所有数学有关的基本上都死了。
所以这里的题目都是相对其他考的而言简单的题qwq,然而我考场上还是不会做
写完之后发现只会分块和线段树qwq,偶尔有点网络流,其他都不会,awsl

3.18

第一天来就考NOI NO.2的题目。。

题目看这里吧

more?more!

这道题非常奇妙的地方在于
因为\(n\)是固定的所以\(n+1\)本就是不需要求的状态,
然后对于\(O(n^2)\)就是\(f_{n+1,i}=f_{n,i}*p^i+f_{n,i-1}*(1-p)^{n-i+1}\)
利用\(f_{n+1,i}\)是可以从两个方程中转移过来的,我们就可以得出有效状态\(f_{n,i}\)了。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#define ll long long
using namespace std;
const ll N=1e6+6;
const ll mod=998244353;
ll n,p,inv[N],finv[N],f[N];
ll read(){ll x=0,w=1;char ch=getchar();while(ch>'9'||ch<'0'){if(ch=='-')w=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*w;
}void init(){inv[1]=1;finv[1]=1;f[1]=1;for(ll i=2;i<=n;i++)inv[i]=(mod-mod/i)*inv[mod%i]%mod;for(ll i=2;i<=n;i++)finv[i]=finv[i-1]*inv[i]%mod;for(ll i=2;i<=n;i++)f[i]=f[i-1]*i%mod;
}ll ksm(ll x,ll k){ll ans=1;while(k){if(k&1)ans=(ans*x)%mod;x=(x*x)%mod;k>>=1;}return ans%mod;
}int main(){freopen("more.in","r",stdin);freopen("more.out","w",stdout);n=read();p=read();init();if(p==499122177){for(ll i=1;i<n;i++){ll sum=((finv[n-i]*finv[i])%mod)*f[n]%mod;sum=(sum%mod*ksm(ksm(p,n-i)%mod,i))%mod;printf("%lld ",sum);}}else {ll sum=1,tmp;for(ll i=1;i<n;i++){tmp=ksm(((ksm(p,i)-ksm((1-p+mod)%mod,i)+mod)%mod),mod-2)%mod;sum=sum*(tmp*((ksm(p,n-i+1)-ksm((1-p+mod)%mod,n-i+1)+mod)%mod)%mod)%mod;printf("%lld ",sum);}}return 0;
}

3.19

唯一比较容易的一天qwq

题目看这里吧

这里是官方题解

T1

数据结构维护dp
第一题就是要下放很多的线段求满足条件的下方,二位偏序,然后卡线段树。
二位偏序排个序就好了(我不会说我这个没想到qwq)
线段树维护dp最大值->树状数组维护
什么?你说树状数组\(log^2\),因为这里我们的序列是单调的,所以直接下放直接查就可以了,这种树状数组只能在这种情况下用。
别人线段树比我树状数组快系列qwq
哦对了,因为这道题叫fc,然后在Windows下面对拍也是fc,就变成了跑了两次这个代码,并没有比较文件输出。所以它全程没给我跑出错误,搞得我当时以为A了。

#include<bits/stdc++.h>
#define ll long long
#define ls root<<1
#define rs root<<1|1
#define max(a,b) a>b?a:b
using namespace std;
const ll N=1e6+5;
ll vis[21],n,m,ti[N],ai[N],ans,s[21];
ll f[N],id[N];
ll read(){ll x=0,w=1;char ch=getchar();while(ch>'9'||ch<'0'){if(ch=='-')w=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*w;
}void work_20(){for(ll i=0;i<(1<<n);i++){ll sum=0,flag=0;memset(vis,0,sizeof(vis));for(ll j=1;j<=n;j++)if((1<<(j-1))&i)vis[j]=1;for(ll j=1;j<=n;j++)s[j]=s[j-1]+vis[j];for(ll j=1;j<=n;j++)if(vis[j]&&((s[min(j+ti[j],n)]-s[j-1]>1)||(s[j]-s[max(0ll,j-ti[j]-1)]>1)))flag=1;if(flag)continue;for(ll j=1;j<=n;j++)if(vis[j])sum+=ai[j];ans=max(sum,ans);}cout<<ans<<endl;
}void work_15(){ll ans=0;for(ll i=1;i<=n;i++)f[i]=ai[i];for(ll i=1;i<=n;i++)for(ll j=0;j<i;j++){if(i-ti[i]<=j||ti[j]+j>=i)continue;f[i]=max(f[i],f[j]+ai[i]);}for(int i=1;i<=n;i++)ans=max(ans,f[i]);cout<<ans<<endl;
}ll mx[N<<2],mx2[N<<2],lazy[N<<2];void update(int root,int left,int right,int v){if(left==right){mx[root]=f[left];return ;}int mid=(left+right)>>1;if(mid>=v) update(ls,left,mid,v);if(mid<v)  update(rs,mid+1,right,v);mx[root]=max(mx[ls],mx[rs]);
}ll query(int root,int left,int right,int l,int r){if(left>r||right<l)return -99999999;if(left>=l&&right<=r)return mx[root];ll a=-99999999,b=-99999999,mid=(left+right)>>1;if(mid>=l) a=query(ls,left,mid,l,r);if(mid<r)  b=query(rs,mid+1,right,l,r);return max(a,b);
}bool cmp(int a,int b){return a+ti[a]<b+ti[b];
}ll c[N];void add(ll x){for(ll i=x;i<=n;i+=(i&(-i)))c[i]=max(c[i],f[x]);
}ll ask(ll x){ll ans=0;for(ll i=x;i>=1;i-=(i&(-i)))ans=max(c[i],ans);return ans;
}int main(){freopen("fc.in","r",stdin);freopen("fc.out","w",stdout);n=read();ll flag=1;for(int i=1;i<=n;i++){ti[i]=read();if(ti[i]!=ti[1])flag=0;}for(int i=1;i<=n;i++)ai[i]=read()*ti[i];for(int i=1;i<=n;i++)ti[i]--,id[i]=i;if(n<=20){work_20();return 0;}if(n<=5000){work_15();return 0;}for(ll i=1;i<=n;i++)f[i]=ai[i];if(flag){for(ll i=1;i<=n;i++){if(i-ti[i]-1>=1)f[i]=query(1,1,n,1,i-ti[i]-1)+ai[i];update(1,1,n,i);    }}else {sort(id+1,id+n+1,cmp);int now=1;for(int i=1;i<=n;i++){while(id[now]+ti[id[now]]<i&&now<=n)add(id[now]),now++;if(i-ti[i]-1>=1)f[i]=ask(i-ti[i]-1)+ai[i];}}for(int i=1;i<=n;i++)ans=max(ans,f[i]);printf("%lld\n",ans);return 0;
}

T2

就是因为这个东西,本来我已经放弃学SAM了的qwq。
是关于SAM的模板题吧qwq
就是考关于SAM的拼接。因为每个序列只能贡献连续的一段,所以我们从n到1把每个字符串的SAM连接起来。就是建的时候记录一下左右端点。然后拼起来,具体看代码吧。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
using namespace std;
const int N=4e6+5;
const int mod=1e9+7;
int f[N],n,a[N],tot,last,tmp[5],rt,ls[N],rs[N];
char s[N],ss[N],b[N];
struct node{int ch[7],len,ff;
}t[N];
int dfs(int x){if(f[x]!=-1)return f[x];f[x]=1;for(int i=1;i<=4;i++){f[x]+=dfs(t[x].ch[i]);f[x]%=mod;}return f[x];
}void print(int x,int k){puts(ss);for(int i=1;i<=4;i++){if(t[x].ch[i]){ss[k]=b[i];print(t[x].ch[i],k+1);}}ss[k]=0;
}void update(int x){int p=last,np=last=++tot;t[np].len=t[p].len+1;while(p&&!t[p].ch[x])t[p].ch[x]=np,p=t[p].ff;if(!p)t[np].ff=rt;else {int q=t[p].ch[x];if(t[q].len==t[p].len+1)t[np].ff=q;else{int nq=++tot;t[nq]=t[q];t[nq].len=t[p].len+1;t[q].ff=t[np].ff=nq;while(p&&t[p].ch[x]==q){t[p].ch[x]=nq;p=t[p].ff;}}}
}int main(){freopen("copy.in","r",stdin);freopen("copy.out","w",stdout);memset(f,-1,sizeof(f));f[0]=0;a['A']=1;a['C']=2;a['G']=3;a['T']=4;b[1]='A';b[2]='C';b[3]='G';b[4]='T';cin>>n;for(int i=1;i<=n;i++){ls[i]=last=rt=++tot;scanf("%s",s+1);int len=strlen(s+1);for(int i=1;i<=len;i++)update(a[s[i]]);rs[i]=tot;}for(int i=n;i>=1;i--){for(int j=rs[i];j>=ls[i];j--){for(int k=1;k<=4;k++){if(!t[j].ch[k])t[j].ch[k]=tmp[k];}}for(int k=1;k<=4;k++)tmp[k]=t[ls[i]].ch[k];}int k;cin>>k;if(k)print(1,0);printf("%d\n",dfs(1));return 0;
}

T3

卡常有点恶心啊qwq
首先对于子序列我们需要用序列自动机(这并不是一个很高大上的东西)维护,不然你会跑很多的重复子序列
肉眼可见的二分图匹配。但是如果我们把每个字符串的子序列都提出来连边建图不就炸了吗
所以套路就在于我们对于每个字符串只要搞出300个关于它的子序列就可以了。
因为这样就一定可以全部匹配了。
好了目前时间复杂度\(O(n^4)\),二分啊。
反正我的程序被卡了一点点时限,也可能有点错误吧,所以我有一个点是打表的。
然后网络流是一定跑不过的别想了,然后我必须搞出1000个关于它的子序列才可以?
如果有大佬可以看看我错哪里,蒟蒻感激不尽

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<map>
#include<vector>
#include<queue>
using namespace std;
vector<int>q[305][305];
map<string,int>mp,mp2;
const int N=301*301*50+5;
const int inf=1e9;
int n,tot,head[301],s,t,ans,cnt,nex[301][31],idx,a[301],ai[301];
int num=1,dep[N],line[N],Q[100001],vis[100001];
string ss[N],sss;
struct node{int to,nex,c;
}e[N];void add(int from,int to){e[++num].to=to;e[num].nex=head[from];head[from]=num;
}int dfs(int x){for(int i=head[x];i;i=e[i].nex){int v=e[i].to;if(vis[v])continue;vis[v]=1;if(!Q[v]||dfs(Q[v])){Q[v]=x;return 1;}}return 0;
}int get(){int ans=0;for(int i=1;i<=n;i++){for(int i=1;i<=tot;i++)vis[i]=0;ans+=dfs(i);}return ans;
}int find(){int l=1,r=n;ans=-1;while(r>=l){int mid=(l+r+1)>>1;num=0;memset(head,0,sizeof(head));for(int i=1;i<=tot;i++)Q[i]=0;for(int i=1;i<=n;i++){for(int j=1;j<=mid;j++)for(int k=0;k<q[i][j].size();k++)add(i,q[i][j][k]);//add(q[i][j][k],i);}if(get()==n){r=mid-1;for(int i=n+1;i<=tot;i++)if(Q[i])line[Q[i]]=i;ans=mid;}else l=mid+1;}
}//void dfs(int id,int now,int x,int y,string S){
//  if(cnt>310||now>sss.size())return ;cerr<<id<<' '<<now<<' '<<x<<' '<<y<<' '<<S<<endl;
//  if(x>=y){
//      if(!mp[S])mp[S]=++tot,ss[tot]=S;
//      if(!vis[mp[S]])cnt++,q[id][y].push_back(mp[S]),vis[mp[S]]=1;return ;
//  }dfs(id,now+1,x+1,y,S+sss[now]);dfs(id,now+1,x,y,S);
//}void init(){int n=sss.size();for(int i=n;i>=1;i--){for(int j=1;j<=26;j++)nex[i-1][j]=nex[i][j];  if(i!=n)nex[i-1][sss[i]-'a'+1]=i;}
}void dfs(int id,int x,int y,int limit,string S){if(cnt>1000||x>sss.size())return ;if(y>=limit){cnt++;if(!mp[S])mp[S]=++tot,ss[tot]=S;q[id][limit].push_back(mp[S]);return ;}for(int i=1;i<=26;i++)if(nex[x][i])dfs(id,nex[x][i],y+1,limit,S+(char)(i+'a'-1));
}int main(){freopen("diff.in","r",stdin);freopen("diff.out","w",stdout);ios::sync_with_stdio(false);cin>>n;tot=n;int flag=0;for(int i=1;i<=n;i++){cnt=0;cin>>sss;int l=sss.size();if(sss=="hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh")flag=1;if(!flag){init();string S;S+=sss[0];for(int j=1;j<=l;j++){dfs(i,0,1,j,S);dfs(i,0,0,j,"");if(cnt>1000)break;}}if(flag){ai[i]=sss.size();while(a[ai[i]])ai[i]--;a[ai[i]]=1;}}   if(flag){cout<<300<<endl;for(int i=1;i<=n;i++){for(int j=1;j<=ai[i];j++)cout<<'h';cout<<endl;}return 0;}s=0,t=tot+1,find();if(ans==-1){cout<<ans<<endl;return 0;}else cout<<ans<<endl;for(int i=1;i<=n;i++)cout<<ss[line[i]]<<endl;return 0;
}

3.20

今天自闭了,没交,盯着电脑看了四个小时。

会改正的只有这一道

网上有题解自己搜吧,据说还是错的。
就是因为区间有包含情况所以不能这么转移。

第二题就是加强版天天爱跑步,给你一颗树,m条路径,问你路径相交的个数,注路径有起点时间和终点时间,不相交于点上也是可以的,gaojiaxuan说还可以加强???

第三题就是较强版八邻桥,八邻桥阵2333,就是变成了m条河道,你要怎么修。

3.22

又是自闭的一天。

题目

第一题构造。没得人写,写的都是随机。

第二题多项式相关,wsl

第三题,考场上算错复杂度了算出来的是\(O(n*logn*\sqrt n)\)
其实是\(O(n*log\sqrt n*\sqrt n)\)
就是对于题目,我每次修改只会多出两个区间来,那么用set维护区间,对于每个区间直接\((log^2)\)改,因为均摊下来最多\((n+q)\)个区间所以是接近\(O(n*log^2)\)的,主席树维护。
好了说一大堆,其实我根本没用这个方法。还是分块好.jpg
对于分块,直接维护每个块的乘积,然后修改的话打标记,修改时因为每个整块有b满了和没满的,所以维护b满了的一个数组,然后块内二分当前满了的然后快速幂没满的。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
const ll N=1e6+5;
const ll mod=1e9+7;
ll l[N],r[N],ans,a[N],b[N],c[N];
ll mul[N],s[N],bl[N],f[N];
ll n,q,tmp,mx[N];
ll read(){ll x=0,w=1;char ch=getchar();while(ch>'9'||ch<'0'){if(ch=='-')w=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*w;
}ll ksm(ll x,ll k){ll ss=1;while(k){if(k&1)ss=(ss*x)%mod;x=(x*x)%mod;k>>=1;}return ss%mod;
}void build(){tmp=sqrt(n);for(ll i=1;i<=tmp;i++)l[i]=(i-1)*tmp+1,r[i]=tmp*i;if(r[tmp]<n)tmp++;l[tmp]=r[tmp-1]+1,r[tmp]=n;for(ll i=1;i<=tmp;i++){for(ll j=l[i];j<=r[i];j++)mx[i]=max(mx[i],a[j]),bl[j]=i,c[j]=b[j];sort(c+l[i],c+r[i]+1);for(ll j=l[i];j<=r[i];j++){mul[j]=c[j];if(j>l[i])mul[j]=(mul[j]*mul[j-1])%mod;}ll sum=1;for(ll j=l[i];j<=r[i];j++)sum=(sum*min(b[j],a[j]))%mod;s[i]=sum;}
}void change(ll x,ll y){b[x]=y;s[bl[x]]=1;for(ll i=l[bl[x]];i<=r[bl[x]];i++)c[i]=b[i];sort(c+l[bl[x]],c+r[bl[x]]+1);for(ll i=l[bl[x]];i<=r[bl[x]];i++){mul[i]=c[i];if(i>l[bl[x]])mul[i]=(mul[i]*mul[i-1])%mod;}if(f[bl[x]]){for(ll i=l[bl[x]];i<=r[bl[x]];i++)s[bl[x]]=(s[bl[x]]*min(f[bl[x]],b[i]))%mod;}else for(ll i=l[bl[x]];i<=r[bl[x]];i++)s[bl[x]]=(s[bl[x]]*min(a[i],b[i]))%mod;
}ll add(ll x,ll y){f[x]=mx[x]=y;s[x]=1;ll u=lower_bound(c+l[x],c+r[x]+1,y)-c-1;if(u+1<=r[x])s[x]=(ksm(y,r[x]-u))%mod;if(u>r[x])u=r[x];if(u>=l[x])s[x]=(s[x]*mul[u])%mod;
}int main(){freopen("magic.in","r",stdin);freopen("magic.out","w",stdout);n=read();q=read();for(ll i=1;i<=n;i++)a[i]=read();for(ll i=1;i<=n;i++)a[i]=max(a[i],a[i-1]);for(ll i=1;i<=n;i++)b[i]=read();build();for(ll i=1;i<=q;i++){ll opt=read();ans=1;if(opt==0){ll x=read(),y=read(),ss=0;if(f[bl[x]])for(ll i=l[bl[x]];i<=r[bl[x]];i++)a[i]=max(a[i],f[bl[x]]);f[bl[x]]=0;for(ll i=x;i<=r[bl[x]];i++)a[i]=max(a[i],y),mx[bl[x]]=max(a[i],mx[bl[x]]);s[bl[x]]=1;for(ll i=l[bl[x]];i<=r[bl[x]];i++)s[bl[x]]=(s[bl[x]]*min(a[i],b[i]))%mod;ll j=bl[x]+1;while(mx[j]<y&&j<=tmp)add(j,y),j++;if(j<=tmp){for(ll k=l[j];k<=r[j];k++)a[k]=max(a[k],max(f[j],y));s[j]=1;for(ll k=l[j];k<=r[j];k++)s[j]=(s[j]*min(a[k],b[k]))%mod;}for(ll j=1;j<=tmp;j++)ans=(ans*s[j])%mod;printf("%lld\n",ans%mod);}else {ll x=read(),y=read();change(x,y);for(ll j=1;j<=tmp;j++)ans=(ans*s[j])%mod;printf("%lld\n",ans%mod);}}return 0;
}

3.23

考了CJ他们的题目
本来就是因为CJ不收去的JZ。然后我在JZ考CJ。ZYYS

第一题。。。分类讨论后没打了,自我感觉和毒瘤很像
第二题。。。神仙组合不过被gaojiaxuan用了一个套路然后好像是可以多项式做出来,据会多项式的人说特别简单比题解良心多了。

只会网络流

考虑最小割。
S连体力流量为1,T连智力流量为1,然后把天数拆点,拆点之间连边流量为1。
然后按题目要求把天数和任务连inf边。
就是说要么这天必须选,要么就是这天要做的任务之前已经被做完了。
一个让人误认为是跑最大答案的网络流。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
const int N=1e5+5;
const int inf=1e9;
int num=1,head[N],k;
int vis[N],dep[N],ti[N],n,m,s,t;
struct node{int to,nex,c;
}e[N<<1];
int read(){int x=0,w=1;char ch=getchar();while(ch>'9'||ch<'0'){if(ch=='-')w=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*w;
}void add(int from,int to,int c){e[++num].to=to;e[num].c=c;e[num].nex=head[from];head[from]=num;
}bool bfs(){memset(dep,0,sizeof(dep));dep[s]=1;queue<int>q;q.push(s);while(!q.empty()){int u=q.front();q.pop();for(int i=head[u];i;i=e[i].nex){int v=e[i].to;if(!dep[v]&&e[i].c)q.push(v),dep[v]=dep[u]+1;}}return dep[t];
}int dfs(int x,int cap){if(x==t)return cap;int addx=0;for(int i=head[x];i;i=e[i].nex){int v=e[i].to;if(dep[v]==dep[x]+1&&e[i].c){int tmp=dfs(v,min(e[i].c,cap-addx));e[i].c-=tmp;e[i^1].c+=tmp;addx+=tmp;}}return addx;
}int dinic(){int ans=0;while(bfs())ans+=dfs(s,inf);return ans;
}int main(){freopen("deadline.in","r",stdin);freopen("deadline.out","w",stdout);n=read();m=read();k=read();s=0;t=m+m+n+1;for(int i=1;i<=m;i++)add(i,i+m,1),add(i+m,i,0);for(int i=1;i<=n;i++){ti[i]=read();if(ti[i])add(i+m+m,t,1),add(t,i+m+m,0);else add(s,i+m+m,1),add(i+m+m,s,0);}for(int i=1;i<=k;i++){int x=read(),y=read();if(!ti[x]) add(x+m+m,y,inf),add(y,x+m+m,0);else  add(y+m,x+m+m,inf),add(x+m+m,y+m,0);}printf("%d\n",dinic());return 0;
}

3.25

没有更正题目。想知道题目问问租酥雨大佬他出的省选联考吧。
反正数学那么多我是自闭了。

3.26

题目
样例

好像是最大子权闭合图的模板题吧。
对于维护两颗不同的树共同连通块,我们考虑对于每一个根跑一次网络流,把它按照题目描述建边,也就是把两颗树的边放到一棵树里面,注意在网络流里的意思是,学了它,它往上的父亲也都被学了,这样就可以维护连通块了。
又不知道为什么,我建图的树边不能重复。也就是两点之间只能有一条inf边。但是fish和jeff的可以???

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
const int N=2e3+5;
const int inf=1e7;
int n,s,t,num,head[N],dep[N],ch[101][101];
int ans=0,sum=0,a[N],cnt=0;
struct edge{int to,nex,c;
}e[N*100];
int read(){int x=0,w=1;char ch=getchar();while(ch>'9'||ch<'0'){if(ch=='-')w=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*w;
}
void add(int from,int to,int c){num++;e[num].to=to;e[num].c=c;e[num].nex=head[from];head[from]=num;
}
struct node{int num=0,head[N];edge e[N*100];void clean(){memset(head,0,sizeof(head));num=0;}void add(int from,int to){num++;e[num].to=to;e[num].nex=head[from];head[from]=num;}
}A,B;
void dfs1(int x,int ff){for(int i=A.head[x];i;i=A.e[i].nex){int v=A.e[i].to;if(v==ff)continue;if(!ch[v][x])add(v,x,inf),add(x,v,0),ch[v][x]=1;dfs1(v,x);}
}
void dfs2(int x,int ff){for(int i=B.head[x];i;i=B.e[i].nex){int v=B.e[i].to;if(v==ff)continue;if(!ch[v][x])add(v,x,inf),add(x,v,0),ch[v][x]=1;dfs2(v,x);}
}
bool bfs(){ memset(dep,0,sizeof(dep));dep[s]=1;int tot=0;queue<int>q;q.push(s);while(!q.empty()){int u=q.front();q.pop();for(int i=head[u];i;i=e[i].nex){int v=e[i].to;if(!dep[v]&&e[i].c)dep[v]=dep[u]+1,q.push(v);}}return dep[t];
}int dfs(int x,int cap){if(x==t)return cap;int addx=0;for(int i=head[x];i;i=e[i].nex){int v=e[i].to;cnt++;if(dep[v]==dep[x]+1&&e[i].c){int tmp=dfs(v,min(cap-addx,e[i].c));e[i].c-=tmp;e[i^1].c+=tmp;addx+=tmp;}}return addx;
}int dinic(){int ans=0;while(bfs())cnt=0,ans+=dfs(s,inf);return ans;
}void solve(){n=read();ans=inf;sum=0;s=0;t=n+1;A.clean();B.clean();int ff=1;for(int i=1;i<=n;i++)a[i]=read(),sum+=a[i]>0?a[i]:0;for(int i=1;i<n;i++){int x=read(),y=read();A.add(x,y);A.add(y,x);}for(int i=1;i<n;i++){int x=read(),y=read();B.add(x,y);B.add(y,x);}for(int i=1;i<=n;i++){memset(ch,0,sizeof(ch));memset(head,0,sizeof(head));num=1;for(int j=1;j<=n;j++){if(a[j]>0)add(s,j,a[j]),add(j,s,0);else add(j,t,-a[j]),add(t,j,0);}dfs1(i,i);dfs2(i,i);int tmp=dinic();ans=min(ans,tmp);}printf("%d\n",sum-ans);
}int main(){freopen("name.in","r",stdin);freopen("name.out","w",stdout);int T=read();while(T--)solve();return 0;
}

3.27

事先说明这道题不卡\(log^3\)
题目
题解

题解应该已经很清楚了吧qwq

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<cmath>
#include<queue>
#define ls root<<1
#define rs root<<1|1
using namespace std;
const int N=5e5+5;
const int inf=1e9;
int lazy[N<<2],s[N<<2];
int n,m,num,head[N],wi[N],dep[N];
int size[N],fa[N],st[N][21],ed[N][21];
int visd[N],visb[N],idd[N],idb[N],bfsid,dfsid;
struct edge{int to,nex;
}e[N<<1];
int read(){int x=0,w=1;char ch=getchar();while(ch>'9'||ch<'0'){if(ch=='-')w=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*w;
}void add(int from,int to){num++;e[++num].to=to;e[num].nex=head[from];head[from]=num;
}struct node{int c[N];void add(int x){for(int i=x;i<=n;i+=(i&(-i)))c[i]+=1;}int query(int x){int ans=0;for(int i=x;i;i-=(i&(-i)))ans+=c[i];return ans;}
}T;void dfs(int x){idd[x]=++dfsid;visd[dfsid]=x;size[x]=1;for(int i=head[x];i;i=e[i].nex){int v=e[i].to;if(dep[v])continue;dep[v]=dep[x]+1;fa[v]=x;dfs(v);size[x]+=size[v];}
}void bfs(){queue<int>q;q.push(1);while(!q.empty()){int x=q.front();q.pop();idb[x]=++bfsid;visb[bfsid]=x;for(int i=head[x];i;i=e[i].nex){int v=e[i].to;if(v==fa[x])continue;q.push(v);}}
}void init(int x){int left=0,right=0;for(int i=head[x];i;i=e[i].nex){int v=e[i].to;if(v==fa[x])continue;init(v);}st[x][0]=idb[x];ed[x][0]=idb[x];for(int i=1;i<=20;i++){left=right=0;for(int j=head[x];j;j=e[j].nex){int v=e[j].to;if(v==fa[x]||!st[v][i-1])continue;if(!left)left=v;right=v;}st[x][i]=st[left][i-1];ed[x][i]=ed[right][i-1];if(st[x][i]>ed[x][i])swap(st[x][i],ed[x][i]);}
}void build(int root,int l,int r){if(l==r){s[root]=wi[visb[l]];return ;}int mid=(l+r)>>1;build(ls,l,mid);build(rs,mid+1,r);s[root]=min(s[ls],s[rs]);
}void push(int root,int left,int right){int mid=(left+right)>>1;lazy[ls]+=lazy[root];lazy[rs]+=lazy[root];s[ls]+=lazy[root];s[rs]+=lazy[root];lazy[root]=0;return ;
}void update(int root,int left,int right,int l,int r,int v){if(left>=l&&right<=r){s[root]-=v;lazy[root]-=v;return ;}if(lazy[root])push(root,left,right);int mid=(left+right)>>1;if(mid>=l) update(ls,left,mid,l,r,v);if(mid<r)  update(rs,mid+1,right,l,r,v);s[root]=min(s[ls],s[rs]);
}void update2(int root,int left,int right,int k){if(left==right){s[root]=inf;return ;}if(lazy[root])push(root,left,right);int mid=(left+right)>>1;if(mid>=k) update2(ls,left,mid,k);if(mid<k)  update2(rs,mid+1,right,k);s[root]=min(s[ls],s[rs]);
}int query(int root,int left,int right,int k){int mid=(left+right)>>1;if(left==right){return left;}if(lazy[root])push(root,left,right);if(s[ls]==k) return query(ls,left,mid,k);else return query(rs,mid+1,right,k);
}int ask(int root,int left,int right,int k){int mid=(left+right)>>1;if(left==right){return s[root];}if(lazy[root])push(root,left,right);if(mid>=k) return ask(ls,left,mid,k);else return ask(rs,mid+1,right,k);
}int main(){freopen("pang.in","r",stdin);freopen("pang.out","w",stdout);n=read();for(int i=1;i<=n;i++)wi[i]=read();for(int i=1;i<n;i++){int x=read(),y=read();add(x,y);add(y,x);}dep[1]=1;dfs(1);bfs();init(1);build(1,1,n);m=read();for(int i=1;i<=m;i++){int opt=read();if(opt==1){int x=read(),y=read(),d=0;for(int i=0;i<=15;i++){if(st[x][i])update(1,1,n,st[x][i],ed[x][i],(int)(y/pow(2,i)));}while(fa[x]&&(int)(y/pow(2,d))){d++;for(int i=1;i<=15;i++)if(st[fa[x]][i]&&st[x][i-1]){update(1,1,n,st[x][i-1],ed[x][i-1],-(int)(y/pow(2,i+d)));}x=fa[x];for(int i=0;i<=15;i++)if(st[x][i]){update(1,1,n,st[x][i],ed[x][i],(int)(y/pow(2,i+d)));}}while(s[1]<=0){int tmp;T.add(idd[visb[tmp=query(1,1,n,s[1])]]);update2(1,1,n,tmp);}}else{int x=read();printf("%d\n",T.query(idd[x]+size[x]-1)-T.query(idd[x]-1));}}return 0;
}

后记

还有两天就要回来啦,省选退役预定了。

转载于:https://www.cnblogs.com/hhh1109/p/10617271.html

中山纪念中学培训杂题(难的都不在这里面qwq)相关推荐

  1. 中山纪念中学培训15天总结

    比赛 2018/7/6-纪中某C组题[jzoj1192,jzoj1397,jzoj1736] 上来就集体爆零 2018/7/7-纪中某C组题[jzoj1494,jzoj1495,jzoj1496,jz ...

  2. 1.17-1.28中山纪念中学培训总结

    这是我第一次来纪中培训, 在这个高手云集的地方,我感受到了自己的渺小.比我优秀的人多了去了,这让我意识到人外有人,天外有天,也激发了我奋斗的动力. 在一次次的全力以赴的比赛中,我收获了新的知识和技巧, ...

  3. 中山纪念中学培训DAY1

    哇啊啊啊啊啊啊$--$ 并不像说环境怎么样. $Day1$模拟赛 稳重一点选了提高$B$ 然后$5min$后: $t1$装压$DP$最短路 $t2$裸地贪心 $t3--$哇$t3$怎么做啊啊啊啊. $ ...

  4. 中山纪念中学 培训 日记

    哇-- 一晃, 还有$3$天就要回去了 真的有点舍不得呢 在大家都说这里的环境$**$的时候 为什么本小可爱真的和大家想法不一样呢-- 呜呜呜-- 首先, 谈一谈备受吐槽的食堂吧 并没有什么不好吃呢 ...

  5. 2019中山纪念中学夏令营-Day14 图论初步【dijkstra算法求最短路】

    Dijkstra是我学会的第一个最短路算法,为什么不先去学SPFA呢?因为我在luogu上翻到了一张比较神奇的图: 关于SPFA -它死了 以及网上还有各位大佬的经验告诉我:SPFA这玩意很容易被卡. ...

  6. 中山纪念中学套题(1)

    哈哈哈,本博客的第一张,讲的就是我在中山纪念中学的一套普及组的题目. ----------------------------------------------------------------- ...

  7. 中山纪念中学集训日志

    7.31 下了一天的雨,坐了一天的车. 中山纪念中学,满目绿树朱瓦,历史感挺浓的. 想起了一年前,我兴致勃勃地看苏卿念的纪中培训日记,没想到一年后,我亲身来到了纪中. 在宿舍跟蚊帐搏斗了许久,真是剪不 ...

  8. 2019中山纪念中学夏令营-Day21[JZOJ]

    2019中山纪念中学夏令营-Day21[JZOJ] 提高组(B组模拟赛)Team_B (由于本人太弱,并没有订正完题目) (题解大部分是从官方题解文件上摘来的) 日常膜拜大神:じやゆん蒟蒻 正文部分: ...

  9. 【2012年中山纪念中学信息学竞赛初一选拔赛一】美丽的纪中(a)

    [2012年中山纪念中学信息学竞赛初一选拔赛一]美丽的纪中(a) (File IO): input:a.in output:a.out 时间限制: 1000 ms 空间限制: 262144 KB [题 ...

最新文章

  1. NeurIPS 2021六篇杰出论文公布,谷歌工程师11年前论文获时间检验奖
  2. Linux系统使用apt命令安装java
  3. 分时系统的用户具有独占性,因此一个用户可以独占计算机系统的资源.,课件2016计算机操作系统试题库(判断).doc...
  4. mysql从大到小排序_sql语句时间排序 sql语句按照时间排序
  5. 这一天,我用 Rust 重写了已有 19 年历史的 C++ 库!
  6. (转)栈与堆栈的区别
  7. 账号跟帐号、账户跟帐户的区别
  8. html加大字号代码,HTML网页字体大小的设置
  9. Android 在现有项目中引入Compose
  10. sql 大于 小于 大于等于 小于等于 符号
  11. Hibernate逍遥游记-第13章 映射实体关联关系-005双向多对多(使用组件类集合\composite-element\)...
  12. Golang 计算MD5值
  13. Unity 图片定点缩放功能
  14. 浙大PatC语言练习50-76
  15. Java多线程模式(一)
  16. 窗口桌面置顶(主窗口和子窗口)
  17. 关于使用github布置定时任务给别人哟
  18. 作为程序猿要多注意身体(华佗教你睡觉)
  19. 基于vue和ElementUI时间选择控件的封装
  20. 第一篇【Python】基础-关东升-专题视频课程

热门文章

  1. 使用python创建文件夹
  2. 普通用户使用docker
  3. cpu对寄存器的访问速度最快
  4. Nervos 双周报第 3 期
  5. 干货分享—Niushop数据库配置
  6. 2022年9月青少年软件编程(Python) 等级考试试卷(一级)
  7. php 后缀文件怎么打开,php是什么文件格式,php扩展名文件如何打开?
  8. css 并排放置两个div
  9. 浅析智能网联产业发展与变化趋势
  10. linux视频播放器mplayer,ubuntu 视频播放器mplayer