CF567

CF567A

在最小点和最大点之间选即可。

点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inl inline
#define endl '\n'
#define gc cin.get
#define pc cout.put
const int N=1e5+5;
const int M=1e7+5;
const int inf=0x7fffffff;
const int mod=997;
const int base=13131;
inl int read(){
    int x=0,f=1;char c=gc();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=gc();}
    while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=gc();}
    return x*f;
}
inl void write(int x){
    if(x<0){pc('-');x=-x;}
    if(x>9)write(x/10);
    pc(x%10+'0');
}
inl void writei(int x){write(x);pc(' ');}
inl void writel(int x){write(x);pc('\n');}
int n,m,a[N];
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    n=read();
    for(int i=1;i<=n;i++)a[i]=read();
    for(int i=1;i<=n;i++){
        int x=min(i^1?a[i]-a[i-1]:inf,i^n?a[i+1]-a[i]:inf),y=max(a[i]-a[1],a[n]-a[i]);
        cout<<x<<' '<<y<<endl;
    }
    return 0;
}

CF567B

按提议模拟,动态维护人数,对于凭空冒出来的人,把他当成一开始就在,最大值+1即可。

点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inl inline
#define endl '\n'
#define gc cin.get
#define pc cout.put
const int N=1e6+5;
const int M=1e7+5;
const int inf=0x7fffffff;
const int mod=997;
const int base=13131;
inl int read(){
    int x=0,f=1;char c=gc();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=gc();}
    while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=gc();}
    return x*f;
}
inl void write(int x){
    if(x<0){pc('-');x=-x;}
    if(x>9)write(x/10);
    pc(x%10+'0');
}
inl void writei(int x){write(x);pc(' ');}
inl void writel(int x){write(x);pc('\n');}
int n,m,a[N],res,t[N],now;
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    n=read();
    for(int i=1;i<=n;i++){
        char c;cin>>c;
        if(c=='+')t[read()]=1,now++;
        else{
            int x=read();
            if(!t[x])res++;
            else t[x]=0,now--;
        }
        res=max(res,now);
    }
    cout<<res<<endl;
    return 0;
}

CF567C

开两个map维护前两个信息即可。

点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inl inline
#define int ll
#define endl '\n'
#define gc cin.get
#define pc cout.put
const int N=1e6+5;
const int M=1e7+5;
const int inf=0x7fffffff;
const int mod=997;
const int base=13131;
inl int read(){
    int x=0,f=1;char c=gc();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=gc();}
    while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=gc();}
    return x*f;
}
inl void write(int x){
    if(x<0){pc('-');x=-x;}
    if(x>9)write(x/10);
    pc(x%10+'0');
}
inl void writei(int x){write(x);pc(' ');}
inl void writel(int x){write(x);pc('\n');}
int n,m,k,a[N],res;
map<int,int>f,g;
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    n=read();k=read();
    for(int i=1;i<=n;i++){
        a[i]=read();
        if(!(a[i]%(k*k)))
            if(g.find(a[i]/(k*k))!=g.end())res+=g[a[i]/(k*k)];
        if(!(a[i]%k))
            if(f.find(a[i]/k)!=f.end())g[a[i]/k]+=f[a[i]/k];
        f[a[i]]++;
    }
    cout<<res<<endl;
    return 0;
}

CF567D

开multiset维护每个连续段。
可以发现,对于长度为 \(k\) 的段,能放置的数量为 \(\lfloor\cfrac{k+1}{a+1}\rfloor\)

然后炮轰的段拆成两部分,重算贡献即可。
注意set按左端点排序后 两个左端点相同的块无法共存 所以用multiset

CF567E

从起点/终点各跑一遍dij,同时维护到达每个点的路径数。
然后对于每条边 \(u->v\)
如果 \(dis_{s->u}+w_i+dis_{v->t}==最短路\)\(cnt_{s->u}*cnt_{v->t}==tot\) 答案 yes
否则看能否通过减边权使 \(dis_{s->u}+w_i+dis_{v->t}<最短路\) 判断剩下情况。
注意方案数很大,需要取模。听说1e9+7被卡了?

另一种做法:抽离出所有可能是最短路的边,求出割边,这样的边一定是Yes

点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inl inline
#define int ll
#define endl '\n'
#define gc cin.get
#define pc cout.put
const int N=2e5+5;
const int M=1e7+5;
const int inf=0x7fffffff;
const int mod=998244353;
const int base=13131;
inl int read(){
    int x=0,f=1;char c=gc();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=gc();}
    while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=gc();}
    return x*f;
}
int n,m,s,t,dis1[N],dis2[N],vis[N],cnt1[N],cnt2[N],pre[N],flag[N];
struct edge{
    int u,v,c;
}e[N];
int head[N],nxt[N],to[N],w[N],cnt;
inl void add(int u,int v,int c){
    nxt[++cnt]=head[u];
    to[cnt]=v;w[cnt]=c;
    head[u]=cnt;
}
inl void dij(int s,int* dis,int* cnt){
    memset(dis,0x3f,sizeof dis1);
    memset(vis,0,sizeof vis);
    priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>>>q;
    q.push({0,s});dis[s]=0;cnt[s]=1;
    while(!q.empty()){
        int x=q.top().second;q.pop();
        if(vis[x])continue;vis[x]=1;
        for(int i=head[x];i;i=nxt[i]){
            int y=to[i],c=w[i];
            if(dis[y]==dis[x]+c)cnt[y]=(cnt[x]+cnt[y])%mod;
            if(dis[y]>dis[x]+c){
                cnt[y]=cnt[x];
                dis[y]=dis[x]+c;
                q.push({dis[y],y});
            }
        }
    }
}
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    n=read();m=read();s=read();t=read();
    for(int i=1;i<=m;i++)e[i]={read(),read(),read()};
    for(int i=1;i<=m;i++)
        add(e[i].u,e[i].v,e[i].c);
    dij(s,dis1,cnt1);
    memset(head,0,sizeof head);
    memset(nxt,0,sizeof nxt);
    cnt=0;
    for(int i=1;i<=m;i++)
        add(e[i].v,e[i].u,e[i].c);
    dij(t,dis2,cnt2);
    for(int i=1;i<=m;i++){
        int u=e[i].u,v=e[i].v,c=e[i].c;
        if(dis1[u]+c+dis2[v]==dis1[t]&&cnt1[u]*cnt2[v]%mod==cnt1[t])cout<<"YES"<<endl;
        else{
            int ans=dis1[u]+c+dis2[v]-dis1[t]+1;
            if(ans>c-1)cout<<"NO"<<endl;
            else cout<<"CAN"<<' '<<ans<<endl;
        }
    }
    return 0;
}

CF567F

\(f_{l,r}\) 表示填完 \([1,l]\) \([r,2n]\) 的方案数。
可以从 \(f_{l-2,r}/f_{l-1,r-1}/f_{l,r-2}\) 转移,多出来的两位填一个数。
没填的一定比他们大,填完的一定比他们小,根据大小判断能否转移。
实现细节很多。

点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inl inline
#define int ll
#define endl '\n'
#define gc cin.get
#define pc cout.put
const int N=2e2+5;
const int M=1e7+5;
const int inf=0x7fffffff;
const int mod=998244353;
const int base=13131;
inl int read(){
    int x=0,f=1;char c=gc();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=gc();}
    while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=gc();}
    return x*f;
}
int n,m,f[N][N];
struct node{
    int op,to;
};
vector<node>v[N];
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    n=read();m=read();
    while(m--){
        int x,y,op;string s;
        cin>>x>>s>>y;
        if(s==">")op=0;
        if(s=="<")op=1;
        if(s==">=")op=2;
        if(s=="<=")op=3;
        if(s=="=")op=4;
        v[x].push_back({op,y});
        v[y].push_back({op^1,x});
    }
    f[0][n<<1|1]=1;
    for(int i=2;i<=n<<1;i+=2){
        for(int l=0,r=(n<<1)-i+1;r<=(n<<1|1);l++,r++){
            if(l&&r){
                int flag=1,pos1=l,pos2=r;
                for(auto k:v[pos1]){
                    int op=k.op,y=k.to;
                    if(op==0&&pos1<=y&&y<=pos2)flag=0;
                    if(op==1&&(y<=pos1||y>=pos2))flag=0;
                    if(op==2&&pos1<y&&y<pos2)flag=0;
                    if(op==3&&(y<pos1||y>pos2))flag=0;
                    if(op>=4&&(y^pos1&&y^pos2))flag=0;
                }
                for(auto k:v[pos2]){
                    int op=k.op,y=k.to;
                    if(op==0&&pos1<=y&&y<=pos2)flag=0;
                    if(op==1&&(y<=pos1||y>=pos2))flag=0;
                    if(op==2&&pos1<y&&y<pos2)flag=0;
                    if(op==3&&(y<pos1||y>pos2))flag=0;
                    if(op>=4&&(y^pos1&&y^pos2))flag=0;
                }
                f[l][r]+=flag*f[l-1][r+1];
            }
            if((n<<1)-r+1>=2){
                int flag=1,pos1=r+1,pos2=r;
                for(auto k:v[pos1]){
                    int op=k.op,y=k.to;
                    if(op==0&&l+1<=y&&y<=r+1)flag=0;
                    if(op==1&&(y<l+1||y>r-1))flag=0;
                    if(op==2&&l+1<=y&&y<=r-1)flag=0;
                    if(op==3&&(y<l+1||y>r+1))flag=0;
                    if(op>=4&&(y^pos1&&y^pos2))flag=0;
                }
                for(auto k:v[pos2]){
                    int op=k.op,y=k.to;
                    if(op==0&&l+1<=y&&y<=r+1)flag=0;
                    if(op==1&&(y<l+1||y>r-1))flag=0;
                    if(op==2&&l+1<=y&&y<=r-1)flag=0;
                    if(op==3&&(y<l+1||y>r+1))flag=0;
                    if(op>=4&&(y^pos1&&y^pos2))flag=0;
                }
                f[l][r]+=flag*f[l][r+2];
            }
            if(l>=2){
                int flag=1,pos1=l-1,pos2=l;
                for(auto k:v[pos1]){
                    int op=k.op,y=k.to;
                    if(op==0&&l-1<=y&&y<=r-1)flag=0;
                    if(op==1&&(y<l+1||y>r-1))flag=0;
                    if(op==2&&l+1<=y&&y<=r-1)flag=0;
                    if(op==3&&(y<l-1||y>r-1))flag=0;
                    if(op>=4&&(y^pos1&&y^pos2))flag=0;
                }
                for(auto k:v[pos2]){
                    int op=k.op,y=k.to;
                    if(op==0&&l-1<=y&&y<=r-1)flag=0;
                    if(op==1&&(y<l+1||y>r-1))flag=0;
                    if(op==2&&l+1<=y&&y<=r-1)flag=0;
                    if(op==3&&(y<l-1||y>r-1))flag=0;
                    if(op>=4&&(y^pos1&&y^pos2))flag=0;
                }
                f[l][r]+=flag*f[l-2][r];
            }
        }
    }
    int ans=0;
    for(int i=0;i<=n<<1;i++)ans+=f[i][i+1];
    cout<<ans/3<<endl;
    return 0;
}
posted @ 2023-12-26 15:05  xiang_xiang  阅读(4)  评论(0编辑  收藏  举报