Codeforces Round #535 (Div. 3)
阿新 • • 發佈:2019-02-17
swa clu blog stream break Edito pri tdi edge
其實也是近一個月之前的一場cf了,div3真是吼啊。今天忽然想起來補完剩下的題。
前五道暴力模擬什麽的略過不寫了。
E2 Array and Segments (Hard version)
題意:給出大小為n的數組a,m個區間。你可以決定每個區間是否進行操作(對區間內的數全部減1),給出任一方案使得數組最大值與最小值的差最大。n<=1e5,m<=300
E2和E1的區別只有數據範圍,E1可以暴力枚舉選擇每個數作為最小值的情況(將包含最小值的區間全部進行操作),每次更新答案,O(n2m)。
E2可以在此基礎上進行改進。線段樹進行區間操作查詢最大值的優化比較好想。然後發現這個m很小…從m入手發現可以用所有區間的端點可以將數組分成不超過601段,在每一段內的i我們按照如上原則選擇的操作是相同的,由此可以批量處理降低時間復雜度。
(然而代碼寫的就非常不優雅,我自己看完都想說這是什麽辣雞…甚至一年半沒寫線段樹了吧。有機會可能會看看官方Tutorial裏的方法重寫。
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<vector> #define Max(a,b) (a>b?a:b) #define N 100005 #define INF 0x3f3f3f3f usingF. MST Unification 題意:給出一個帶權無向圖,你可以增加任意邊的邊權使得最小生成樹唯一。求所增加的邊權總和的最小值。 先用kruskal跑出一個MST,在這個MST上倍增LCA。對於每一條未被加入當前MST的邊進行判斷,如果其邊權與u,v間路徑上的最大邊權相等,則這條邊可以起替代作用,需要給權值+1。namespace std; int read() { int x=0,f=1; char c=getchar(); while(c<‘0‘||c>‘9‘){if(c==‘-‘)f=-1;c=getchar();} while(c>=‘0‘&&c<=‘9‘){x=x*10+c-‘0‘;c=getchar();} return x*f; } int n,m,a[N],l[303],r[303]; int seg[606],ans=0; vector<int>A,cp; struct Node {int l,r,maxn,lazy; }t[N*4]; void build(int idx,int l,int r) { t[idx].l=l,t[idx].r=r; if(l==r){t[idx].maxn=a[l],t[idx].lazy=0;return;} int mid=(l+r)>>1; build(idx<<1,l,mid),build(idx<<1|1,mid+1,r); t[idx].maxn=Max(t[idx<<1].maxn,t[idx<<1|1].maxn); } void pushdown(int idx) { if(t[idx].lazy&&t[idx].l!=t[idx].r) { int lz=t[idx].lazy; t[idx].lazy=0; t[idx<<1].lazy+=lz,t[idx<<1|1].lazy+=lz; t[idx<<1].maxn+=lz,t[idx<<1|1].maxn+=lz; } } void add(int idx,int l,int r,int w) { if(l<=t[idx].l&&r>=t[idx].r) { t[idx].maxn+=w,t[idx].lazy+=w; return; } pushdown(idx); int mid=(t[idx].l+t[idx].r)>>1; if(r<=mid)add(idx<<1,l,r,w); else if(l>mid)add(idx<<1|1,l,r,w); else add(idx<<1,l,r,w),add(idx<<1|1,l,r,w); t[idx].maxn=Max(t[idx<<1].maxn,t[idx<<1|1].maxn); } int main() { n=read(),m=read(); for(int i=1;i<=n;i++)a[i]=read(); build(1,1,n); for(int i=1;i<=m;i++) { l[i]=read(),r[i]=read(); seg[i*2-1]=l[i],seg[i*2]=r[i]; } sort(seg+1,seg+2*m+1),seg[0]=0; int cnt=unique(seg+1,seg+2*m+1)-seg-1; seg[cnt+1]=INF; int now=0,f; for(int i=1;i<=n;i++) { if(i==seg[now]||(i>seg[now]&&i==seg[now+1])) { f=0,cp.clear(); if(i==seg[now+1])now++; for(int j=1;j<=m;j++) { if(l[j]<=i&&r[j]>=i) f++,add(1,l[j],r[j],-1),cp.push_back(j); } } else if(i>seg[now]) { now++,f=0,cp.clear(); for(int j=1;j<=m;j++) { if(l[j]<=seg[now-1]+1&&r[j]>=seg[now]-1) f++,add(1,l[j],r[j],-1),cp.push_back(j); } } int minnum=a[i]-f; if(t[1].maxn-minnum>ans) { ans=t[1].maxn-minnum; A=cp; } if(i==seg[now]-1||i==seg[now]) { for(int j=0;j<cp.size();j++) add(1,l[cp[j]],r[cp[j]],1); } } printf("%d\n%d\n",ans,A.size()); for(int i=0;i<A.size();i++) printf("%d ",A[i]); return 0; }
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> #include<cmath> #define Max(a,b) (a>b?a:b) #define N 200005 using namespace std; int read() { int x=0,f=1;char c=getchar(); while(c<‘0‘||c>‘9‘){if(c==‘-‘)f=-1;c=getchar();} while(c>=‘0‘&&c<=‘9‘){x=x*10+c-‘0‘;c=getchar();} return x*f; } int n,m,head[N],cnt=0,father1[N],dep[N],p[N][20],mlen[N][20]; bool used[N]; struct Node1 { int u,v,w; }Edges1[N]; bool operator < (Node1 A,Node1 B){return A.w<B.w;} struct Node2 { int nxt,to,w; }Edges2[N*2]; int findf(int x) {return (father1[x]==x)?x:(father1[x]=findf(father1[x]));} void addedge(int u,int v,int w) { Edges2[++cnt].nxt=head[u]; head[u]=cnt; Edges2[cnt].to=v,Edges2[cnt].w=w; } void dfs(int u) { for(int i=head[u];~i;i=Edges2[i].nxt) { int v=Edges2[i].to; if(v==p[u][0])continue; p[v][0]=u,dep[v]=dep[u]+1,mlen[v][0]=Edges2[i].w; dfs(v); } } void init() { for(int i=1;(1<<i)<=n;i++) for(int j=1;j<=n;j++) p[j][i]=p[p[j][i-1]][i-1],mlen[j][i]=max(mlen[j][i-1],mlen[p[j][i-1]][i-1]); } int lca(int x,int y) { int res=0; if(dep[x]>dep[y])swap(x,y); int f=dep[y]-dep[x]; for(int i=0;(1<<i)<=f;i++) if(f&(1<<i))res=Max(res,mlen[y][i]),y=p[y][i]; if(x!=y) { for(int i=(int)log2(n);i>=0;i--) if(p[x][i]!=p[y][i])res=Max(res,mlen[x][i]),res=Max(res,mlen[y][i]),x=p[x][i],y=p[y][i]; res=Max(res,mlen[x][0]),res=Max(res,mlen[y][0]),x=p[x][0]; } return res; } int main() { memset(head,-1,sizeof(head)); memset(dep,0,sizeof(dep)); memset(used,0,sizeof(used)); n=read(),m=read(); for(int i=1;i<=m;i++) Edges1[i].u=read(),Edges1[i].v=read(),Edges1[i].w=read(); sort(Edges1+1,Edges1+1+m); for(int i=1;i<=n;i++)father1[i]=i; int cnt=0; for(int i=1;i<=m;i++) { int fu=findf(Edges1[i].u),fv=findf(Edges1[i].v); if(fu!=fv) { cnt++; addedge(Edges1[i].u,Edges1[i].v,Edges1[i].w); addedge(Edges1[i].v,Edges1[i].u,Edges1[i].w); used[i]=1;father1[fu]=fv; } if(cnt==n-1)break; } dep[1]=mlen[1][0]=0;p[1][0]=1; dfs(1),init(); int ans=0; for(int i=1;i<=m;i++) { if(used[i])continue; int u=Edges1[i].u,v=Edges1[i].v; int maxlen=lca(u,v); if(maxlen==Edges1[i].w)ans++; } printf("%d\n",ans); return 0; }
Codeforces Round #535 (Div. 3)