考试过程:看看题面。还是觉得难度较大,按顺序开题。
首先是T1,这道题好像连暴搜都不能打,让我很难受,后来我想到了\(meet-in- the-middle\),这样的复杂度是可以用来打对拍程序的,但是我不想打。
然后想了想正解,想到了找到两个满足条件的点\(s_{i,j-1}==s_{i-1,j}\),我觉得这样是合法的。
这样获得了\(80pts\),但是考完试后被varuxn
\(hack\)掉了,就是当且仅当存在两个点,这两个点其中一个在另一个的左下方的时候,这样就不对了。
然后是T2,基础的暴力分显然是分组背包,很好拿。打完后想了一会优化,但是没什么思路。
然后是T3,我打了\(40pts\),但是有一部分我不会处理,就改成了\(20pts\),但是因为自己在计算的时候\(tot\)没有清零,导致\(RE\)了,挂了\(20\)分。
最后一题暴力分\(10\)分很好拿,但是我没时间打了,以后要注意,每一分都是很重要的,我要合理分配时间。
思路:我想的是找到两个满足条件的点\(s_{i,j-1}==s_{i-1,j}\),但是这样做的局限性就在于我无法保证这两个点之间满足右下的位置关系,那么正解就是利用树状数组,每次进行更新然后查询即可。
代码如下:
#include<bits/stdc++.h>
#define re register int
#define ii inline int
#define iv inline void
#define f() cout<<"fuck"<<endl
#define head heeead
#define next neet
using namespace std;
const int N=1010;
int t,n,m;
char s[N][N];
bool vis[N][N];
ii read()
{
int x=0;char ch=getchar();bool f=1;
while(ch<'0' or ch>'9')
{
if(ch=='-') f=0;
ch=getchar();
}
while(ch>='0' and ch<='9')
{
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return f?x:(-x);
}
struct Yree
{
int tr[N][N];
ii lowbit(int x) {return x&(-x);}
iv add(int x,int y)
{
for(;x<=n;x+=lowbit(x))
{
for(;y<=m;y+=lowbit(y))
tr[x][y]++;
}
}
ii query(int x,int y)
{
int out=0;
for(;x;x-=lowbit(x))
{
for(;y;y-=lowbit(y))
out+=tr[x][y];
}
return out;
}
}T;
signed main()
{
freopen("water.in","r",stdin),freopen("water.out","w",stdout);
t=read();
while(t--)
{
n=read(),m=read();
for(re i=1;i<=n;i++)
scanf("%s",s[i]+1);
bool flag=0;
memset(T.tr,0,sizeof(T.tr));
for(re i=1;i<=n;i++)
{
for(re j=1;j<=m;j++)
{
vis[i][j]=0;
if(i-1>0 and j-1>0)
{
if(s[i][j-1]==s[i-1][j])
{
T.add(i,j);
vis[i][j]=1;
if(T.query(i-1,j-1)) {flag=1;goto bye;}
else if(vis[i-1][j] or vis[i][j-1]) {flag=1;goto bye;}
}
}
}
}
bye:;
if(flag) printf("1\n");
else printf("0\n");
}
return 0;
}
留坑
思路:
注意在\(b\)数组排序的时候要排到\(m\),因为\(n\)和\(m\)不同。
代码如下:
#include<bits/stdc++.h>
#define re register int
#define ii inline int
#define iv inline void
#define f() cout<<"fuck"<<endl
#define head heeead
#define next neet
using namespace std;
const int N=3e5+10;
int n,m,q,ma,mb,tot;
int a[N],b[N],nb[N],na[N],c[N];
struct node
{
int a,pos;
friend bool operator < (node x,node y) {return x.a<y.a;}
}cun[N];
ii read()
{
int x=0;char ch=getchar();bool f=1;
while(ch<'0' or ch>'9')
{
if(ch=='-') f=0;
ch=getchar();
}
while(ch>='0' and ch<='9')
{
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return f?x:(-x);
}
struct Segment_Tree
{
#define mid ((l+r)>>1)
#define lc (rt<<1)
#define rc (rt<<1|1)
int minn[N<<2],lazy[N<<2];
iv pp(int rt) {minn[rt]=min(minn[lc],minn[rc]);}
iv pd(int rt)
{
if(lazy[rt]!=0)
{
minn[lc]+=lazy[rt];
minn[rc]+=lazy[rt];
lazy[lc]+=lazy[rt];
lazy[rc]+=lazy[rt];
lazy[rt]=0;
}
}
iv insert(int rt,int l,int r,int p,int z)
{
if(l==r)
{
minn[rt]=z;
return;
}
if(mid>=p) insert(lc,l,mid,p,z);
else insert(rc,mid+1,r,p,z);
pp(rt);
}
iv change(int rt,int l,int r,int L,int R,int z)
{
if(L>R) return;
if(L<=l and r<=R)
{
minn[rt]+=z,lazy[rt]+=z;
return;
}
pd(rt);
if(mid>=L) change(lc,l,mid,L,R,z);
if(mid<R) change(rc,mid+1,r,L,R,z);
pp(rt);
}
ii query(int rt,int l,int r)
{
return minn[rt];
}
#undef mid
#undef lc
#undef rc
}T;
inline bool com(node x,node y) {return x.a>y.a;}
signed main()
{
freopen("problem.in","r",stdin),freopen("problem.out","w",stdout);
n=read(),m=read();
for(re i=1;i<=n;i++) a[i]=read(),cun[i]=(node){a[i],i},na[i]=a[i];
for(re i=1;i<=m;i++) b[i]=read(),nb[i]=b[i];
sort(cun+1,cun+n+1,com);
sort(nb+1,nb+m+1);
for(re i=1;i<=n;i++)
{
int p=lower_bound(nb+1,nb+m+1,i)-nb;
c[i]=m-p+1;
}
int sum=0;
for(re i=1;i<=n;i++)
{
sum+=c[i]-cun[i].a;
T.insert(1,1,n,i,sum);
}
sort(na+1,na+n+1);
q=read();
int opt,x,p;
while(q--)
{
opt=read(),x=read();
bool flag=1;
if(opt==1)
{
p=upper_bound(na+1,na+n+1,a[x])-na-1;
++na[p];
++a[x];
T.change(1,1,n,n-p+1,n,-1);
}
else if(opt==2)
{
p=lower_bound(na+1,na+n+1,a[x])-na;
--na[p];
--a[x];
T.change(1,1,n,n-p+1,n,1);
}
else if(opt==3)
{
++b[x];
if(b[x]<=n) T.change(1,1,n,b[x],n,1);
}
else if(opt==4)
{
--b[x];
if(b[x]<n) T.change(1,1,n,b[x]+1,n,-1);
}
if(T.query(1,1,n)>=0) printf("1\n");
else printf("0\n");
}
return 0;
}