省选模拟(20200326)
今天的考试和NOI online冲突了,于是只写了一个多小时,本来在想一会T1就切掉额
T1 灯
发现更改的位置可以直接遍历,这样的话就有了一个小于根号的做法
于是我们可以在修改的过程中改掉对大块的影响,大块之间直接记个数组就行了
AC_code
#include<bits/stdc++.h>
using namespace std;
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
int s=0,t=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')t=-1;ch=getchar();}
while(isdigit(ch)){s=(s<<1)+(s<<3)+(ch^48);ch=getchar();}
return s*t;
}
const int N=1e5+5;
int n,m,q,a[N],v[N],ans;
vector<int> vec[N];
int sum[505][505],add[N],lsh[N],lh,ys[N];
signed main(){
freopen("light.in","r",stdin);
freopen("light.out","w",stdout);
n=read();m=read();q=read();
fo(i,1,n){
a[i]=read();
vec[a[i]].push_back(i);
}
ans=0;int sq=sqrt(n);
fo(i,1,n){
if(a[i+1]!=a[i]&&vec[a[i+1]].size()<=sq)add[a[i]]++;
}
fo(i,1,n)if(vec[i].size()>sq){
lsh[++lh]=i;ys[i]=lh;
}
fo(i,1,n)if(ys[a[i]]&&ys[a[i+1]]&&a[i]!=a[i+1])sum[ys[a[i]]][ys[a[i+1]]]++;
while(q--){
int x=read();
if(vec[x].size()>sq){
ans+=add[x];add[x]=-add[x];
fo(i,1,lh)if(i!=ys[x]){
if(v[x]){
if(v[lsh[i]])ans+=sum[i][ys[x]];
else ans-=sum[ys[x]][i];
}
else {
if(v[lsh[i]])ans-=sum[i][ys[x]];
else ans+=sum[ys[x]][i];
}
}
v[x]^=1;printf("%d\n",ans);
continue;
}
for(int i:vec[x]){
if(v[a[i]]){
if(a[i-1]!=a[i]){
if(v[a[i-1]]){
ans++;
add[a[i-1]]--;
}
else add[a[i-1]]++;
}
if(a[i+1]!=a[i]){
if(!v[a[i+1]]){
ans--;
add[a[i+1]]++;
}
else add[a[i+1]]--;
}
}
else {
if(a[i-1]!=a[i]){
if(v[a[i-1]]){
ans--;
add[a[i-1]]++;
}
else add[a[i-1]]--;
}
if(a[i+1]!=a[i]){
if(!v[a[i+1]]){
ans++;
add[a[i+1]]--;
}
else add[a[i+1]]++;
}
}
}
v[x]^=1;
printf("%d\n",ans);
}
return 0;
}
T2 十字路口
很是迷惑啊,根本找不到有用的信息呃呃呃
所以有用的只有红灯的时间限制,发现可以连每两次的时间差
AC_code
#include<bits/stdc++.h>
using namespace std;
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
int s=0,t=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')t=-1;ch=getchar();}
while(isdigit(ch)){s=(s<<1)+(s<<3)+(ch^48);ch=getchar();}
return s*t;
}
const int N=1e5+5;
int n,m,ans=-1;
vector<int> a[N];
pair<int,int> tmp[N];
struct E{int to,nxt,val;}e[N*2];
int head[N],rp;
void add_edg(int x,int y,int z){
e[++rp].to=y;e[rp].nxt=head[x];
e[rp].val=z;head[x]=rp;
}
bool vis[N],vs[N];
void dfs(int x,int d){
if(~ans)return ;
if(vis[x])return ans=d,void();
if(vs[x])return ;
vis[x]=vs[x]=true;
for(int i=head[x];i;i=e[i].nxt){
int y=e[i].to;
dfs(y,d+e[i].val);
}
vis[x]=false;
}
signed main(){
freopen("crossing.in","r",stdin);
freopen("crossing.out","w",stdout);
n=read();m=read();
fo(i,1,m){
a[i].resize(n+1);
fo(j,1,n)a[i][j]=read();
}
fo(i,1,n){
int ct=0;
fo(j,1,m)if(a[j][i])tmp[++ct]=make_pair(a[j][i],j);
sort(tmp+1,tmp+ct+1);
fu(j,ct,2){
add_edg(tmp[j].second,tmp[j-1].second,tmp[j].first-tmp[j-1].first);
}
}
fo(i,1,n)if(!vs[i])dfs(i,0);
// dfs(1,0);
printf("%d\n",ans);
return 0;
}
T3 密室逃脱
很像dp的一道题,其实一眼就知道是dp做,但是啥也不会了
其实最后的状态,就是每个格子里必须留下一些人,剩下的全图游走
那么我们可以枚举全图游走的人都在当前点的状态来转移,这样就可以固定每个状态了
AC_code
#include<bits/stdc++.h>
using namespace std;
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
int s=0,t=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')t=-1;ch=getchar();}
while(isdigit(ch)){s=(s<<1)+(s<<3)+(ch^48);ch=getchar();}
return s*t;
}
const int N=1e3+5;
int n,m,a[N],b[N],f[N][N*20],ans,mx;
signed main(){
freopen("escape.in","r",stdin);
freopen("escape.out","w",stdout);
n=read();m=read();mx=m;
fo(i,1,n-1)a[i]=read(),b[i]=read(),mx=max(mx,a[i]+b[i]);
fo(i,0,m-1)f[1][i]=i;
fo(i,1,n-1){
int tmp=0;
fo(j,0,mx){
if(j<a[i]){
tmp=max(tmp,f[i][j]);
f[i+1][j+b[i]]=max(f[i+1][j+b[i]],f[i][j]+b[i]);
}
if(j>=a[i]&&j<a[i]+b[i]){
f[i+1][j-a[i]]=max(f[i+1][j-a[i]],f[i][j]);
}
if(j>=a[i]+b[i]){
f[i+1][j]=max(f[i+1][j],f[i][j]);
}
}
fo(j,0,b[i]-1)f[i+1][j]=max(f[i+1][j],tmp+j);
}
fo(j,0,mx)ans=max(ans,f[n][j]);
printf("%d\n",ans);
return 0;
}
QQ:2953174821