省选模拟(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;
}
posted @ 2022-03-26 19:07  fengwu2005  阅读(50)  评论(0编辑  收藏  举报