J组T4
一道/赛上觉得很难/下来也听说很难/但听老师一讲也觉得只有中位绿/的题。
题目传送门
,
首先想到 \(r=1\) 时的做法,不难看出可以使用一个标记数组来存储,然后依次寻找离他最近的 \(1\) 看是否满足要求,标记即可。\(5\) pts拿到手。
然后发现可以扩展出一种类似递推的思想,设\(f_{i,j}\) 表示在第i轮时能否以j结尾,0为可以,1就不行。那么显而易见的类比上面的过程,只用找到距离当前数最近的有值的f就可以了。
如果仅仅到这里可能只有中位黄,但是题目告诉我们:一个人不能自己接自己的龙。 这里就有一个不太容易想到的思维转换,也就是你可以先去掉上一轮的值,后面在加回来这样就不会产生错误了。期望得分60~85pts看你怎么写。
进行细节上的优化+快读即可过掉本题。
#include<bits/stdc++.h>
using namespace std;
const int N=200005,R=105;
int t,n,k,q,r[N],c[N],now,arr,maxx,maxr,tt,i,j,qq,rr,len[N],mark[R][N];
vector<int> v[N],del[N],the[N];
int in(){int k=0,f=1;char c=getchar();while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}while(c>='0'&&c<='9')k=k*10+c-'0',c=getchar();return k*f;
}
signed main(){t=in();for(tt=1;tt<=t;tt++){maxx=0;n=in(),k=in(),q=in();for(i=1;i<=n;i++){len[i]=in();v[i].clear();del[i].clear();the[i].clear();for(j=0;j<len[i];j++){del[i].push_back(0);the[i].push_back(0);arr=in();maxx=max(maxx,arr);v[i].push_back(arr);}}maxr=0;for(qq=1;qq<=q;qq++) r[qq]=in(),c[qq]=in(),maxr=max(maxr,r[qq]);for(i=0;i<=maxr;i++) for(j=0;j<=maxx;j++) mark[i][j]=0;mark[0][1]=1;for(rr=1;rr<=maxr;rr++){for(i=1;i<=n;i++){now=-1;for(j=0;j<len[i];j++) mark[rr-1][v[i][j]]-=del[i][j];for(j=0;j<len[i];j++){if(now!=-1&&j-now<k){mark[rr][v[i][j]]++;the[i][j]++;}if(mark[rr-1][v[i][j]]>0) now=j;}for(j=0;j<len[i];j++){mark[rr-1][v[i][j]]+=del[i][j];del[i][j]=the[i][j];the[i][j]=0;}}}for(qq=1;qq<=q;qq++){if(mark[r[qq]][c[qq]]){putchar('1');putchar('\n');}else{putchar('0');putchar('\n');}}}return 0;
}
S组T2
题目传送门
没有什么好说的,先想到二分,然后模拟。
注意写代码的时候添加一些注释,变量名规范,尽量多写函数,这样容易调试。后面就是经典dry摄像头模型了。
#include<bits/stdc++.h>using namespace std;
int t,n,m,l,v,cnt,it,ss,len,be,en,mid,kkk,ans,now,jilu,p[200010];
double vv;
bool flag;
struct node{int d;int v;int a;
}c[200010];
struct line{int ll;int rr;
}arr[200010];
int work1(){cnt=0;for(int i=1;i<=n;i++){if(c[i].a==0){if(c[i].v>v&&c[i].d<=p[m]) cnt++;} else if(c[i].a>0){ss=p[m]-c[i].d;if(ss<0) continue;if(c[i].v*c[i].v+2*c[i].a*ss>=0)vv=sqrt(c[i].v*c[i].v+2*c[i].a*ss);else vv=0.000;if(vv>v) cnt++;}else{if(c[i].d<=p[m]){it=lower_bound(p+1,p+1+m,c[i].d)-p;ss=p[it]-c[i].d;if(c[i].v*c[i].v+2*c[i].a*ss>=0)vv=sqrt(c[i].v*c[i].v+2*c[i].a*ss);else vv=0.000;if(vv>v) cnt++;}}}return cnt;
}
bool cmp(line t1,line t2){return t1.rr<t2.rr;
}
int work2(){//zerolen=0;for(int i=1;i<=n;i++){if(c[i].a==0){if(c[i].v>v&&c[i].d<=p[m]){arr[++len].ll=lower_bound(p+1,p+1+m,c[i].d)-p;arr[len].rr=m;}} else if(c[i].a>0){ss=p[m]-c[i].d;if(c[i].v*c[i].v+2*c[i].a*ss>=0)vv=sqrt(c[i].v*c[i].v+2*c[i].a*ss);else vv=0.000;if(vv>v){kkk=lower_bound(p+1,p+1+m,c[i].d)-p;be=kkk;en=m;while(be<=en){mid=(be+en)/2;ss=p[mid]-c[i].d;if(c[i].v*c[i].v+2*c[i].a*ss>=0)vv=sqrt(c[i].v*c[i].v+2*c[i].a*ss);else vv=0.000;if(vv>v){ans=mid;en=mid-1;}else be=mid+1;}arr[++len].ll=ans;arr[len].rr=m;}}else{if(c[i].d<=p[m]){it=lower_bound(p+1,p+1+m,c[i].d)-p;ss=p[it]-c[i].d;if(c[i].v*c[i].v+2*c[i].a*ss>=0)vv=sqrt(c[i].v*c[i].v+2*c[i].a*ss);else vv=0.000;if(vv>v){kkk=lower_bound(p+1,p+1+m,c[i].d)-p;be=kkk;en=m;while(be<=en){mid=(be+en)/2;ss=p[mid]-c[i].d;if(c[i].v*c[i].v+2*c[i].a*ss>=0)vv=sqrt(c[i].v*c[i].v+2*c[i].a*ss);else vv=0.000;
// cout<<be<<" "<<en<<"\n";if(vv>v){ans=mid;be=mid+1;}else en=mid-1;}arr[++len].ll=kkk;arr[len].rr=ans;}}}}//camera
// for(int i=1;i<=len;i++){
// printf("%d %d\n",arr[i].ll,arr[i].rr);
// } sort(arr+1,arr+1+len,cmp);ans=1,now=arr[1].rr;for(int i=2;i<=len;i++){if(now<arr[i].ll){now=arr[i].rr;ans++;} }return ans;
}
signed main(){
// freopen("detect.in","r",stdin);
// freopen("detect.out","w",stdout);scanf("%d",&t);for(int tt=1;tt<=t;tt++){scanf("%d%d%d%d",&n,&m,&l,&v);flag=false;for(int i=1;i<=n;i++){scanf("%d%d%d",&c[i].d,&c[i].v,&c[i].a);if(c[i].a!=0) flag=true;}for(int i=1;i<=m;i++) scanf("%d",&p[i]);
// work2();jilu=work1();if(jilu==0) printf("%d %d\n",jilu,m);else printf("%d %d\n",jilu,m-work2());}return 0;
}
S组T3
谔谔发现我赛场上思路正确但是数组开小。从此养成const好习惯。