CSP 後多校十四(拉格朗日待補)
阿新 • • 發佈:2021-11-14
「構造字串·尋寶·序列·構樹 」
A. 構造字串
複雜度為 \(O(n^2)\) 及以上的時候還是很好想的,不過這題資料過水,\(O(n^2)\) 隨便寫.
考慮怎麼優化,不難發現每個關係之間形成了類似於圖之間的關係.
於是倍增就可以了,不過題解裡寫了一個字符集大小的限制,沒太懂,希望有會的 dalao 能來踹我.
A_code
#include<bits/stdc++.h> using namespace std; namespace BSS{ // #define int long long #define lf double #define pb push_back #define mp make_pair #define lb lower_bound #define ub upper_bound #define Fill(x,y) memset(x,y,sizeof(x)) #define Copy(x,y) memset(x,y,sizeof(x)) #define File(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout) auto read=[](int w=0,bool cit=0,char ch=getchar())->int{ while(!isdigit(ch)) cit|=(ch=='-'),ch=getchar(); while(isdigit(ch)) w=(w<<3)+(w<<1)+(ch^48),ch=getchar(); return cit?(-w):w; }; }using namespace BSS; const int N=1e3+21; int m,n; int fa[N],col[N],vis[N]; vector<int> vec,emp[N]; int find(int x){ return fa[x]==x ? x : fa[x]=find(fa[x]); } signed main(){ File(str); n=read(),m=read(); int x,y,z; for(int i=1;i<=n;i++) fa[i]=i; for(int i=1;i<=m;i++){ x=read(),y=read(),z=read(); for(int j=1;j<=z;j++){ fa[find(x+j-1)]=find(y+j-1); } emp[x+z].pb(y+z),emp[y+z].pb(x+z); } for(int i=1;i<=n;i++){ if(find(i)==i) continue; for(auto j : emp[i]) emp[find(i)].pb(j); } for(int i=1;i<=n;i++){ for(auto j : emp[i]){ if(find(i)==find(j)) puts("-1"),exit(0); } } Fill(col,-1); for(int i=1;i<=n;i++){ if(~col[i]) continue; x=0; for(auto j : emp[find(i)]){ if(~col[j]){ vec.pb(col[j]),x=max(x,col[j]),vis[col[j]]=1; } } for(int j=0,lmj=x+1;j<=lmj;j++){ if(!vis[j]){ col[i]=j; break; } } for(int j=i;j<=n;j++){ if(find(i)==find(j)) col[j]=col[i]; } for(int j=0,lmj=x+1;j<=lmj;j++) vis[j]=0; } for(int i=1;i<=n;i++) printf("%d ",col[i]); exit(0); }
B. 尋寶
簡單題,複雜度沒卡 \(bitset\),不過 \(O(k^3)\) 傳遞閉包也是可以的.
B_code
#include<bits/stdc++.h> using namespace std; namespace BSS{ // #define int long long #define lf double #define pb push_back #define mp make_pair #define lb lower_bound #define ub upper_bound #define Fill(x,y) memset(x,y,sizeof(x)) #define Copy(x,y) memset(x,y,sizeof(x)) #define File(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout) auto read=[](int w=0,bool cit=0,char ch=getchar())->int{ while(!isdigit(ch)) cit|=(ch=='-'),ch=getchar(); while(isdigit(ch)) w=(w<<3)+(w<<1)+(ch^48),ch=getchar(); return cit?(-w):w; }; }using namespace BSS; #define y0 assa #define y1 asas #define y2 sasa #define merge asasasas const int N=1e5+21,M=1e5+21; char ch[N]; int m,n,ms,ns,ts,cnt,tot; int id[N],fa[N],head[N],ans[N],pos[N],vis[N],ru[N]; int find(int x){ return x==fa[x] ? x : fa[x]=find(fa[x]) ; } vector<int> mg[N],rk[N]; bitset<M> con[M]; struct I { int u,v,nxt; } e[N<<1]; auto add=[](int u,int v)->void{ e[++ts].u=u,e[ts].v=v,e[ts].nxt=head[u]; head[u]=ts,ru[u]++; }; auto merge=[](int i,int j)->void{ fa[find(i)]=find(j); }; queue<int> que; auto bfs=[]()->void{ for(int i=1;i<=tot;i++) que.push(i),con[i].set(i,1),vis[i]=1; while(que.size()){ int u=que.front(); que.pop(); for(int i=head[u];i;i=e[i].nxt){ if(con[u]==con[e[i].v]) continue; con[e[i].v]|=con[u]; if(!vis[e[i].v]) que.push(e[i].v); vis[e[i].v]=1; } vis[u]=0; } }; signed main(){ File(treasure); n=read(),m=read(),ms=read(),ns=read(); for(int i=0,lmi=m+1;i<=lmi;i++){ mg[0].pb(0),rk[0].pb(0); mg[n+1].pb(0),rk[n+1].pb(0); } for(int i=1;i<=n;i++){ scanf("%s",ch+1),mg[i].pb(0); for(int j=1;j<=m;j++) mg[i].pb(ch[j]=='.'); mg[i].pb(0); } // for(int i=1;i<=n;i++){ // for(int j=1;j<=m;j++) cout<<mg[i][j]<<' ' ; // puts(""); // } for(int i=1;i<=n;i++){ rk[i].pb(0); for(int j=1;j<=m;j++) rk[i].pb(++cnt),fa[cnt]=cnt; rk[i].pb(0); } for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ if(!mg[i][j]) continue; if(mg[i][j-1]) merge(rk[i][j],rk[i][j-1]); if(mg[i-1][j]) merge(rk[i][j],rk[i-1][j]); if(mg[i][j+1]) merge(rk[i][j],rk[i][j+1]); if(mg[i+1][j]) merge(rk[i][j],rk[i+1][j]); } } int x,y,x1,y1,x2,y2,res; for(int i=1;i<=cnt;i++){ if(find(i)==i) id[i]=++tot,pos[tot]=i; } for(int i=1;i<=ms;i++){ x1=read(),y1=read(),x2=read(),y2=read(); add(id[find(rk[x2][y2])],id[find(rk[x1][y1])]); } bfs(); for(int i=1;i<=ns;i++){ x1=read(),y1=read(),x2=read(),y2=read(); x=find(rk[x1][y1]),y=find(rk[x2][y2]); res=con[id[x]][id[y]]|(x==y),printf("%d \n",res); } exit(0); }
C. 序列
顯然和斜率有關,推著推著腦子就熱了,於是就沒打出來.
李超線段樹確實是很好用的,不過感覺 \(O(nlogn)\) 的 \(CDQ\) 也能寫,由於懶,就沒打.
C_code
#include<bits/stdc++.h> using namespace std; namespace BSS{ #define int long long #define lf double #define pb push_back #define mp make_pair #define lb lower_bound #define ub upper_bound #define Fill(x,y) memset(x,y,sizeof(x)) #define Copy(x,y) memset(x,y,sizeof(x)) #define File(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout) auto read=[](int w=0,bool cit=0,char ch=getchar())->int{ while(!isdigit(ch)) cit|=(ch=='-'),ch=getchar(); while(isdigit(ch)) w=(w<<3)+(w<<1)+(ch^48),ch=getchar(); return cit?(-w):w; }; }using namespace BSS; #define ls (x<<1) #define rs (x<<1|1) const int N=1e6+21,inf=1e15,C=1e6+1,W=2e6+1; int m,n; int a[N],b[N],pa[N],pb[N],ans[N]; struct II { int x,y,id; } q[N]; struct I{ int k,b; I(){} I(int k_,int b_) : k(k_),b(b_) {} inline int calc(int x){ return k*(x-C)+b; } }tr[W<<3]; void build(int x,int l,int r){ tr[x].k=inf,tr[x].b=inf; if(l==r) return ; int mid=(l+r)>>1; build(ls,l,mid),build(rs,mid+1,r); } void ins(int x,int l,int r,I px){ if(px.k==inf) return ; if(tr[x].k==inf or (px.calc(l)<tr[x].calc(l) and px.calc(r)<tr[x].calc(r) )){ return tr[x]=px,void(); } int mid=(l+r)>>1; if(tr[x].k==inf or tr[x].calc(mid)>px.calc(mid)) swap(px,tr[x]); if(tr[x].calc(l)>px.calc(l)) ins(ls,l,mid,px); if(tr[x].calc(r)>px.calc(r)) ins(rs,mid+1,r,px); } int qry(int x,int l,int r,int px){ if(l==r) return (tr[x].k==inf ? inf : tr[x].calc(px)); int mid=(l+r)>>1,res=(tr[x].k==inf ? inf : tr[x].calc(px)); if(px<=mid) res=min(res,qry(ls,l,mid,px)); else res=min(res,qry(rs,mid+1,r,px)); return res; } auto solve=[](int i)->void{ // cout<<q[i].id<<" "<<pa[q[i].x]+pb[q[i].x]*q[i].y<<' '<<qry(1,1,W,q[i].y+C)<<' '<<q[i].y<<" skr\n"; ans[q[i].id]+=pa[q[i].x]+pb[q[i].x]*q[i].y-qry(1,1,W,q[i].y+C); }; auto Work=[]()->void{ build(1,1,W),ins(1,1,W,I(0,0)); sort(q+1,q+1+m,[](II i,II j){ return i.x<j.x; }); for(int i=1;i<=n;i++) pa[i]=pa[i-1]+a[i],pb[i]=pb[i-1]+b[i]; for(int i=1,j=1;i<=n;i++){ while(j<=m and q[j].x==i) solve(j),j++; ins(1,1,W,I(pb[i],pa[i])); } }; signed main(){ File(seq); n=read(),m=read(); int x,y; for(int i=1;i<=n;i++) a[i]=read(),b[i]=read(); for(int i=1;i<=m;i++) q[i].x=read(),q[i].y=-read(),ans[i]-=a[q[i].x]+b[q[i].x]*q[i].y,q[i].id=i; Work(); for(int i=1;i<=m;i++) q[i].x=n-q[i].x+1; reverse(a+1,a+1+n),reverse(b+1,b+1+n); Work(); for(int i=1;i<=m;i++) printf("%lld\n",ans[i]); exit(0); }
D. 構樹
拉格朗日,鴿了.