Codeforces Round #679 Div.1

幸亏没打。。。

A

从小到大排序,模拟。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<climits>
#include<set>
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
#define mp make_pair
using namespace std;
inline int read(){
    int f=1,ans=0;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
    return f*ans;
}
const int MAXN=1e5+11;
int N,A[7],B[7][MAXN];
multiset<int> s;
void Ins(int w){/*cerr<<"Ins:"<<w<<endl;*/s.insert(w);return;}
void Del(int w){/*cerr<<"Del:"<<w<<endl;*/s.erase(s.find(w));return;}
int Qmax(){return *(--s.end());}
struct Node{int w;pii p;}tmp[MAXN*7];
bool cmp(Node x1,Node x2){return x1.w<x2.w;}
int Ps[MAXN],Ans=INT_MAX,tot;
int main(){
    //freopen("in2.txt","r",stdin);
    for(int i=1;i<=6;i++) A[i]=read();sort(A+1,A+7);
    N=read();    
    for(int i=1;i<=N;i++) {int x=read();for(int j=1;j<=6;j++) B[j][i]=x-A[j];}
    for(int i=1;i<=6;i++) for(int j=1;j<=N;j++){++tot;tmp[tot].w=B[i][j],tmp[tot].p=mp(i,j);}
    sort(tmp+1,tmp+tot+1,cmp);
    int ps=1;for(int i=1;i<=N;i++) Ins(B[6][i]),Ps[i]=6;bool ff=1;
    if(N==1){printf("%d\n",0);return 0;}
    while(ps<=tot){
        int l=ps,r;for(r=ps;tmp[r].w==tmp[l].w;r++);r--;
        //cerr<<"l:"<<l<<" r:"<<r<<endl;
        for(int i=l;i<=r;i++) {
            Del(tmp[i].w),Ans=min(Ans,Qmax()-tmp[l].w),Ins(tmp[i].w);
            //cerr<<"res:"<<Qmax()-tmp[l].w<<endl;
            //if(Ans==-199) return 0;
        }
        for(int i=l;i<=r;i++){
            Del(tmp[i].w),Ps[tmp[i].p.se]--;if(!Ps[tmp[i].p.se]) ff=0;
            Ins(B[Ps[tmp[i].p.se]][tmp[i].p.se]);
        }if(!ff) break;
        ps=r+1;
    }
    printf("%d\n",Ans);return 0;
}
View Code

 

B

构造。发现构造的是一个必要解,检验一下正确性。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<climits>
#include<set>
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
#define mp make_pair
using namespace std;
inline int read(){
    int f=1,ans=0;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
    return f*ans;
}
const int MAXN=2e5+11;
char str[3];int N,sta[MAXN],Ans[MAXN],tot;
set<int> s;
void Ins(int w){s.insert(w);return;}
void Del(int w){s.erase(s.find(w));return;}
int Qmax(){return *(--s.end());}
struct node{
    int opt,w;
}tmp[MAXN];int cnt;
int main(){
    //freopen("in1.txt","r",stdin);
    N=read();for(int i=1;i<=N;i++) Ins(i);
    for(int cas=1;cas<=2*N;cas++){
        scanf("%s",str+1);
        if(str[1]=='+'){tmp[++cnt].opt=0;sta[++sta[0]]=++tot;Ans[sta[sta[0]]]=Qmax();Del(Qmax());continue;}
        else{
            int x=read();
            tmp[++cnt].opt=1,tmp[cnt].w=x;
            if(!sta[0]){printf("NO\n");return 0;}
            int ps=sta[sta[0]];
            if(Ans[ps]<x){printf("NO\n");return 0;}
            if(Ans[ps]==x) {sta[0]--;continue;}
            Ins(Ans[ps]);sta[0]--;
            if(s.find(x)!=s.end()){Del(x);Ans[ps]=x;continue;}
            {printf("NO\n");return 0;}
        }
    }
    s.clear();int ps=1;
    for(int i=1;i<=2*N;i++){
        if(!tmp[i].opt) {s.insert(Ans[ps]);ps++;continue;}
        else{
            int x=*s.begin();
            if(x!=tmp[i].w){printf("NO\n");return 0;}
            s.erase(x);
        }
        
    }
    printf("YES\n");
    for(int i=1;i<=N;i++) printf("%d ",Ans[i]);printf("\n");
    return 0;
}
 
View Code

 

C

 

首先当 $a>bc$ 时显然答案为 $-1$ 。

而我们只需要考虑在 $c$ 之前的,因为如果过期了那么还不如从后一段开始优。

如图,记 $k=\dfrac{a}{bd}$ ,则答案为 $a(k+1)-\dfrac{k*(k+1)}{2}bd$。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<climits>
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define int long long
using namespace std;
inline int read(){
    int f=1,ans=0;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
    return f*ans;
}
int A,B,C,D,T;
signed main(){
    T=read();
    while(T--){
        A=read(),B=read(),C=read(),D=read();
        if(A>B*C){printf("-1\n");continue;}
        if(C<=D){printf("%lld\n",A);continue;}
        int K=A/(B*D);
        printf("%lld\n",A*(K+1)-(1+K)*K/2*B*D);
    }return 0;
}
View Code

D

对于符合条件的最长链肯定有一个端点在直径的两个端点上。证明可以考虑相交部分奇偶讨论,可以发现直径一定优于其他。

则直接将两个根摘出来,线段树维护即可。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<algorithm>
#include<climits>
#include<map>
#define pii pair<int,int>
#define pb push_back
#define mp make_pair
#define fi first
#define se second
using namespace std;
inline int read(){
    int f=1,ans=0;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
    return f*ans;
}
const int MAXN=5e5+11;
int N;vector<pii> vec[MAXN];
map<pii,int> M;
struct Tree{
    int rt,siz[MAXN],dfn[MAXN],dis[MAXN],rev[MAXN],Id[MAXN],dep[MAXN];
    void dfs(int u,int fath){
        siz[u]=1;dfn[u]=++dfn[0];dep[u]=dep[fath]+1;rev[dfn[0]]=u;
        if(fath) Id[M[mp(u,fath)]]=u;
        for(auto pp:vec[u]){if(pp.fi!=fath){dis[pp.fi]=dis[u]+pp.se;dfs(pp.fi,u);siz[u]+=siz[pp.fi];}}
        return;
    }
    int Maxn[2][MAXN<<2],tag[MAXN<<2];
    void build(int k,int l,int r){
        if(l==r){Maxn[dis[rev[l]]&1][k]=dep[rev[l]];return;}
        int mid=(l+r)>>1;build(k<<1,l,mid),build(k<<1|1,mid+1,r);
        Maxn[0][k]=max(Maxn[0][k<<1],Maxn[0][k<<1|1]); Maxn[1][k]=max(Maxn[1][k<<1],Maxn[1][k<<1|1]);
        return;
    }
    void pushdown(int k){
        if(!tag[k]) return;
        if(!(tag[k]&1)){tag[k<<1]+=tag[k],tag[k<<1|1]+=tag[k];tag[k]=0;return;}
        swap(Maxn[0][k<<1],Maxn[1][k<<1]),swap(Maxn[0][k<<1|1],Maxn[1][k<<1|1]);
        tag[k<<1]+=tag[k],tag[k<<1|1]+=tag[k];tag[k]=0;return;
    }
    void Add(int k,int l,int r,int x,int y,int w){
        if(x<=l&&r<=y){tag[k]+=w;swap(Maxn[0][k],Maxn[1][k]);return;}
        pushdown(k);int mid=(l+r)>>1;
        if(x<=mid) Add(k<<1,l,mid,x,y,w); if(mid<y) Add(k<<1|1,mid+1,r,x,y,w);
        Maxn[0][k]=max(Maxn[0][k<<1],Maxn[0][k<<1|1]); Maxn[1][k]=max(Maxn[1][k<<1],Maxn[1][k<<1|1]);
        return;
    }
    int Qmax(){return Maxn[0][1];}
    void init(){memset(Maxn,-127/3,sizeof(Maxn)),memset(tag,0,sizeof(tag));dfs(rt,0);build(1,1,N);return;}
    void Add(int id){int u=Id[id];Add(1,1,N,dfn[u],dfn[u]+siz[u]-1,1);return;}
    void Del(int id){int u=Id[id];Add(1,1,N,dfn[u],dfn[u]+siz[u]-1,-1);return;}
    void print(){
        for(int i=1;i<=N;i++) printf("%d %d\n",dis[i],rev[i]);printf("\n");
        return;
    }
}S1,S2;
int dep[MAXN],rt1,rt2,Q,sta[MAXN];
void dfs(int u,int fath){dep[u]=dep[fath]+1;for(auto pp:vec[u]) if(pp.fi!=fath) dfs(pp.fi,u);}
int main(){
    //freopen("A.in","r",stdin);
    N=read();for(int i=1;i<N;i++){int u=read(),v=read(),w=read();sta[i]=w;M[mp(u,v)]=M[mp(v,u)]=i;vec[u].pb(mp(v,w)),vec[v].pb(mp(u,w));}
    dfs(1,0);int Max=1,ps=1;for(int i=2;i<=N;i++) if(dep[i]>Max) Max=dep[i],ps=i;
    rt1=ps;dfs(rt1,0);Max=1,ps=rt1;for(int i=1;i<=N;i++) if(dep[i]>Max) Max=dep[i],ps=i; rt2=ps;
    S1.rt=rt1,S2.rt=rt2;S1.init(),S2.init();
    //S1.print();
    //S1.print();return 0;
    Q=read();
    while(Q--){
        int x=read();
        //cerr<<sta[x]<<endl;
        if(!sta[x]){S1.Add(x),S2.Add(x);sta[x]^=1;}
        else if(sta[x]){S1.Del(x),S2.Del(x);sta[x]^=1;}
        int res1=S1.Qmax(),res2=S2.Qmax();
        printf("%d\n",max(res1,res2)-1);
        //return 0;
    }return 0;
}
View Code

 

posted @ 2020-10-27 22:33  siruiyang_sry  阅读(132)  评论(0编辑  收藏  举报