题目传送门
分析:
神仙题2333
网络流本身索然无味,关键就是这个恶心的建图
首先每个力度向可以演奏的音符连边,边数n*m直接爆炸
然后考虑优化
联想a+b problem试着使用主席树
但是发现由于两个关键字都是区间,所以前缀连边没有用
然后考虑线段树合并,在最底层节点上可持久化
点数貌似是n*log(n)^2吧
好像可以写
写写写。。。
真恶心。。。
然后wsm,n=4e5,m=3e6的网络流它能过2000ms啊2333
神仙复杂度
#include<cstdio> #include<cstring> #include<cmath> #include<queue> #include<algorithm> #pragma GCC optimize(3) #define maxn 400005 #define maxm 3000005 #define INF 0x3f3f3f3f using namespace std; inline int getint() { int num=0,flag=1;char c; while((c=getchar())<‘0‘||c>‘9‘)if(c==‘-‘)flag=-1; while(c>=‘0‘&&c<=‘9‘)num=num*10+c-48,c=getchar(); return num*flag; } int n,m,K,S,T; int fir[maxn],nxt[maxm],to[maxm],cap[maxm],cnt; int h[maxn],tp[maxn]; vector<int>G[maxn]; int H[maxn],sz[maxn]; int rt[maxn],lc[maxn],rc[maxn],cur; inline void newnode(int u,int v,int w) {to[++cnt]=v,nxt[cnt]=fir[u],fir[u]=cnt,cap[cnt]=w;} inline void insert(int u,int v,int w) {newnode(u,v,w),newnode(v,u,0);} inline bool bfs() { memset(h,-1,sizeof h); queue<int>Q;h[S]=0,Q.push(S); while(!Q.empty()) { int u=Q.front();Q.pop(); for(int i=fir[u];i;i=nxt[i]) if(cap[i]&&!~h[to[i]]) { h[to[i]]=h[u]+1,Q.push(to[i]); if(to[i]==T)return 1; } } return 0; } inline int aug(int u,int flow) { if(u==T)return flow; int used=0; for(int i=tp[u];i;i=nxt[i]) { tp[u]=i; if(cap[i]&&h[to[i]]==h[u]+1) { int w=flow-used; w=aug(to[i],min(cap[i],w)); cap[i]-=w,cap[i^1]+=w,used+=w; if(used==flow)return flow; } } if(!used)h[u]=-1; return used; } inline int dinic() { int num=0; while(bfs())memcpy(tp,fir,sizeof fir),num+=aug(S,INF); return num; } inline void Insert(int &now,int l,int r,int i) { now=++cur; if(l==r){insert(T+now,i,INF);return;} int mid=(l+r)>>1; if(H[i]<=mid)Insert(lc[now],l,mid,i),insert(T+now,T+lc[now],INF); else Insert(rc[now],mid+1,r,i),insert(T+now,T+rc[now],INF); } inline void Link(int now,int l,int r,int ql,int qr,int u) { if(!now)return; if(ql<=l&&r<=qr){insert(u,T+now,INF);return;} int mid=(l+r)>>1; if(ql<=mid)Link(lc[now],l,mid,ql,qr,u); if(qr>mid)Link(rc[now],mid+1,r,ql,qr,u); } inline int Merge(int u,int v,int l,int r) { if(!u||!v)return u+v; int tmp=++cur; if(l==r) { insert(T+tmp,T+u,INF),insert(T+tmp,T+v,INF); return tmp; } int mid=(l+r)>>1; if((lc[tmp]=Merge(lc[u],lc[v],l,mid)))insert(T+tmp,T+lc[tmp],INF); if((rc[tmp]=Merge(rc[u],rc[v],mid+1,r)))insert(T+tmp,T+rc[tmp],INF); return tmp; } inline void dfs(int u) { Insert(rt[u],1,n,u); for(int i=0;i<sz[u];i++)dfs(G[u][i]),rt[u]=Merge(rt[u],rt[G[u][i]],1,n); } int main() { n=getint(),m=getint(); for(int i=2;i<=n;i++) { int u=getint(); G[u].push_back(i),sz[u]++; } S=n+m+1,T=S+1;cnt=1; for(int i=1;i<=n;i++)H[i]=getint(),insert(i,T,1); dfs(1); for(int i=1;i<=m;i++) { int l=getint(),r=getint(),u=getint(),t=getint(); insert(S,i+n,t),Link(rt[u],1,n,l,r,i+n); } printf("%d\n",dinic()); }
原文:https://www.cnblogs.com/Darknesses/p/12019623.html