咕了十几场了,还是写一写吧。。
T1 玩水
发现满足三个人路径不同必须要有2个及以上的斜线相同结构,需要注意如果同一行或者同一列的话必须要相邻才行。
#include<bits/stdc++.h>
using namespace std;
char a[1050][1050];
int c[1050][1050],n,t,m;
inline void add(int x,int y,int val)
{ for(int i=x;i<=n;i+=i&-i)
for(int j=y;j<=m;j+=j&-j)
++c[i][j];
}
inline int query(int x,int y)
{ int res=0;
for(int i=x;i;i-=i&-i)
for(int j=y;j;j-=j&-j)
res+=c[i][j];
return res;
}
signed main()
{ freopen("water.in","r",stdin);
freopen("water.out","w",stdout);
scanf("%d",&t);
while(t--)
{ int ji=0;
scanf("%d%d",&n,&m); bool bo=0;
for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)c[i][j]=0;
for(int i=1;i<=n;++i)scanf("%s",a[i]+1);
for(int i=2;i<=n;++i)
{ for(int j=1;j<m;++j)
{ if(a[i][j]==a[i-1][j+1])add(i,j,1);
if(a[i][j]==a[i-1][j+1] and query(i,j)>=2){bo=1;break;}
}if(bo)break;
}
if(n==2)
{ bo=0;
for(int i=1;i<m-1;++i)if(a[2][i]==a[1][i+1] and a[2][i+1]==a[1][i+2])bo=1;
}
if(bo)puts("1");
else puts("0");
}
return 0;
}
T2 假人
待补。。
T3 切题
如果方案可行,对于最大的k个$a_i$ ,总有$\sum_{i=1}{m}min(b_i,k)>=\sum_{i=1}ka_i$。
将 b 的统计方式转换,设$c_i$为大于等于 i 的 b 的个数,那么上式为$\sum_{i-1}^{k}c_i$
于是可以线段树维护最小值。修改的话需要记录每个$a_i$的第一次和最后一次出现位置。
#include<bits/stdc++.h>
using namespace std;
int fir[564545],sec[554545];
int n,m,b[250001],a[250001],tmp[250001],q,val[250001],c[250001];
int minn[250010<<3],tag[250010<<3];
inline void pushup(int x){minn[x]=min(minn[x<<1],minn[x<<1|1]);}
inline void pushdown(int x){minn[x<<1]+=tag[x];minn[x<<1|1]+=tag[x];tag[x<<1]+=tag[x];tag[x<<1|1]+=tag[x];tag[x]=0;}
inline void build(int x,int l,int r)
{ if(l==r){minn[x]=val[l];return ;}
int mid=(l+r)>>1;
build(x<<1,l,mid);build(x<<1|1,mid+1,r);
pushup(x);
}
inline void update(int x,int l,int r,int L,int R,int val)
{ if(l>=L and r<=R){minn[x]+=val;tag[x]+=val;return;}
if(tag[x]!=0)pushdown(x);
int mid=(l+r)>>1;
if(mid<R)update(x<<1|1,mid+1,r,L,R,val);
if(mid>=L)update(x<<1,l,mid,L,R,val);
pushup(x);
}
signed main()
{ freopen("problem.in","r",stdin);
freopen("problem.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i)scanf("%d",&a[i]),tmp[i]=a[i];
for(int i=1;i<=m;++i)scanf("%d",&b[i]);
sort(tmp+1,tmp+1+n);
for(int i=1;i<=m;++i)c[min(b[i],n)]++;
for(int i=n-1;i;--i)c[i]+=c[i+1];
c[0]=0;for(int i=1;i<=n;++i)c[i]+=c[i-1];
for(int i=n,sum=0;i;--i)
{ sum+=tmp[i];
val[n-i+1]=c[n-i+1]-sum;
}
for(int i=n;i;--i)if(!fir[tmp[i]])fir[tmp[i]]=n-i+1;
for(int i=1;i<=n;++i)if(!sec[tmp[i]])sec[tmp[i]]=n-i+1;
build(1,1,n);scanf("%d",&q);
for(int i=1;i<=q;++i)
{ int opt,pos;
scanf("%d%d",&opt,&pos);
if(opt==1)
{ int pre=a[pos];
a[pos]++;
int p=fir[pre];
update(1,1,n,p,n,-1);
if(!fir[a[pos]] and !sec[a[pos]])sec[a[pos]]=p;
else fir[a[pos]]=p,sec[a[pos]]=p;
if(fir[pre]==sec[pre])fir[pre]=sec[pre]=0;
else fir[pre]=p+1;
printf("%d\n",minn[1]>=0);
}
if(opt==2)
{ int pre=a[pos];a[pos]--;
int p=sec[pre];
update(1,1,n,p,n,1);
if(!fir[a[pos]] and !sec[a[pos]])fir[a[pos]]=p;
else fir[a[pos]]=p,sec[a[pos]]=p;
if(fir[pre]==sec[pre])fir[pre]=sec[pre]=0;
else sec[pre]=p-1;
printf("%d\n",minn[1]>=0);
}
if(opt==3)
{ ++b[pos];
if(b[pos]<=n)update(1,1,n,b[pos],n,1);
printf("%d\n",minn[1]>=0);
}
if(opt==4)
{ --b[pos];
if(b[pos]<n)update(1,1,n,b[pos]+1,n,-1);
printf("%d\n",minn[1]>=0);
}
}
}
T4 天下第一
LCT维护连通性不会,待补。。