CSP 后多校十四
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. 构树
拉格朗日,鸽了.