CF1413 (Div.2)

硬生生把上分赛打成下分赛/baojin

$\text{A}$

注意到 $n$ 是偶数,直接将相邻的交换一下, $ans_{2i}=-a_{2i+1} \  ans_{2i+1}=a_{2i}$ 即可

$code$ :

#include<cstdio>
#include<cctype>

#define maxn 1111

inline int read(){
    int r=0,f=0;
    char c;
    while(!isdigit(c=getchar()))f|=(c=='-');
    while(isdigit(c))r=(r<<1)+(r<<3)+(c^48),c=getchar();
    return f?-r:r;
}

inline int abs(int a){
    return a<0?-a:a;
}

int n,a[maxn],ans[maxn];

inline void work(){
    n=read();
    for(int i=1;i<=n;i++)a[i]=read();
    for(int i=1;i<=n;i+=2)
        ans[i]=-a[i+1],ans[i+1]=a[i];
    for(int i=1;i<=n;i++)printf("%d ",ans[i]);
    puts("");
}

int main(){
    int t=read();
    while(t--)work(); 
    return 0;
}

 

$\text{B}$

因为每个数不同,我们就找到第一列,然后按照第一列的顺序输出即可

#include<cstdio>
#include<cctype>

#define maxn 555

inline int read(){
    int r=0,f=0;
    char c;
    while(!isdigit(c=getchar()))f|=(c=='-');
    while(isdigit(c))r=(r<<1)+(r<<3)+(c^48),c=getchar();
    return f?-r:r;
}

inline int abs(int a){
    return a<0?-a:a;
}

int n,m,r[maxn][maxn],c[maxn][maxn],ans[maxn];

inline void work(){
    n=read(),m=read();
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            r[i][j]=read();
    for(int i=1;i<=m;i++)
        for(int j=1;j<=n;j++)
            c[i][j]=read();
    for(int k=1;k<=m;k++){
        bool ok=0;
        for(int i=1;i<=n;i++)
            if(r[i][1]==c[k][1]){
                ok=1;
                break;
            }
        if(!ok)continue;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                if(c[k][i]==r[j][1])ans[i]=j;
        break;
    }
    for(int i=1;i<=n;i++,puts(""))
        for(int j=1;j<=m;j++)
            printf("%d ",r[ans[i]][j]);
}

int main(){
    int t=read();
    while(t--)work(); 
    return 0;
}

 

$\text{C}$

考试的时候双指针写挂了,就写了一个 $O(nlogn \times log10^9 \times 36)$ 的,但是少爷机让过了 /se

先将 $a$ , $b$ 排序,考虑二分答案,怎么 $check$ ?在里面任意找一个值做最大值(设为 $Max$ ),那么满足条件的最小值就很好求了( $Min=Max-ans$ )

然后对于 $\forall i \in [1,n]$ 我们要满足 $\exists j \in [1,6]$ 使得 $Min \le b_i-a_j \le Max$ ,同时加上 $a_j$ ,就是要满足 $Min+a_j \le b_i \le Max+a_j$

然后相当于有 $6$ 个区间,就看看区间之间(就是所有区间都覆盖不到的地方)有没有点( $b_i$ ),如果有就无法满足条件。

$code$ :

#include<cstdio>
#include<cctype>
#include<algorithm>

using namespace std;

#define maxn 101101

inline int read(){
    int r=0,f=0;
    char c;
    while(!isdigit(c=getchar()))f|=(c=='-');
    while(isdigit(c))r=(r<<1)+(r<<3)+(c^48),c=getchar();
    return f?-r:r;
}

inline int min(int a,int b){
    return a<b?a:b;
}

inline int max(int a,int b){
    return a>b?a:b;
}

int n,a[11],b[maxn];

inline bool has(int l,int r){
    return b[lower_bound(b+1,b+1+n,l)-b]<=r;
}

inline bool check(int x){
    for(int i=1;i<=n;i++)
        for(int j=1;j<=6;j++){
            int Max=b[i]-a[j];
            int Min=Max-x;
            if(Min<0)continue;
            if(b[1]<Min+a[1])continue;
            if(b[n]>Max+a[6])continue;
            int lst=0;
            bool ok=1;
            for(int k=1;k<=6;k++){
                if(lst>=Min+a[k]){
                    lst=Max+a[k];
                    continue;
                }
                if(has(lst+1,Min+a[k]-1)){
                    ok=0;
                    break;
                }
                lst=Max+a[k];
            }
            if(ok)return true;
        }
    return false;
}

int main(){
    for(int i=1;i<=6;i++)a[i]=read();
    sort(a+1,a+7);
    n=read();
    for(int i=1;i<=n;i++)b[i]=read();
    sort(b+1,b+1+n);
    int l=-1,r=b[n]-b[1];
    while(l+1<r){
        int mid=(l+r)>>1;
        if(check(mid))r=mid;
        else l=mid;
    }
    printf("%d\n",r);
    return 0;
}

 

$\text{D}$

考虑用树状数组 + 栈来做,对于一个 $+$ 直接丢到栈里面去

对于一个 $-$ ,首先看货架上还有没有东西,再看前面的连续一段 $-$ 中的最大值有没有大于当前 $x$ ,如果都没有,就出栈存答案

然后就发现 $\text{WA} \  \text{on} \  \text{56}$ 了 /baojin ,我们发现没有考虑一种情况,可能连续一段 $-$ 确实没有大于 $x$ 的,但是因为这连续一段拿完了与上一段连续 $-$ 中间的 $+$ ,那么实际上还要与上一段的 $Max$ 取大,似乎可以用并查集维护,然而发现其实就是求当前栈顶元素的后缀最大值,用树状数组维护即可

$code$ :

#include<cstdio>
#include<cctype>

#define maxn 101101

#define lowbit(k) (k&(-k))

inline int read(){
    int r=0,f=0;
    char c;
    while(!isdigit(c=getchar()))f|=(c=='-');
    while(isdigit(c))r=(r<<1)+(r<<3)+(c^48),c=getchar();
    return f?-r:r;
}

inline char get_c(){
    char c=getchar();
    while(c!='+'&&c!='-')c=getchar();
    return c;
}

inline int max(int a,int b){
    return a>b?a:b;
}

int n,cnt,top,c[maxn],cm[maxn],sta[maxn],ans[maxn];

inline void add(int k,int x){
    for(;k<=n;k+=lowbit(k))c[k]+=x;
}

inline int sum(int k){
    int s=0;
    for(;k>0;k-=lowbit(k))s+=c[k];
    return s;
}

inline void addm(int k,int x){
    for(;k>0;k-=lowbit(k))cm[k]=max(cm[k],x);
}

inline int askm(int k){
    int Max=0;
    for(;k<=n;k+=lowbit(k))Max=max(Max,cm[k]);
    return Max;
}

int main(){
    n=read();
    for(int i=1;i<=n;i++)add(i,1);
    for(int i=1;i<=2*n;i++){
        char c=get_c();
        if(c=='+'){
            cnt++;
            sta[++top]=cnt;
            continue;
        }
        if(!top)return puts("NO"),0;
        int x=read();
        if(askm(sta[top])>x)return puts("NO"),0;
        if(sum(n)-sum(x-1)<top)return puts("NO"),0;
        ans[sta[top]]=x;
        addm(sta[top],x);
        add(x,-1);
        top--;
        
    }
    puts("YES");
    for(int i=1;i<=n;i++)printf("%d ",ans[i]);
    return 0;
}

 

$\text{E}$

显然,当 $a>b \times c$ 时,输出 $-1$

否则当 $c \le d$ 时,输出 $a$

接下来我能造成的伤害肯定要在 $c$ 时间内打完,所以考虑二分打的次数(其实可以直接算出来,但是懒得算) 

然后注意, $check$ 应当是看 $a \le b \times d \times (mid-1)$ ,就是说我打这一次还会让怪物扣血,不然其实怪物是加血,最后答案会变劣

然后最后答案就是 $tim \times a - b \times d \times \frac{tim(tim-1)}{2}$ ,用等差数列算一下就可以算出该式

$code$ :

#include<cstdio>
#include<cctype>

inline int read(){
    int r=0,f=0;
    char c;
    while(!isdigit(c=getchar()))f|=(c=='-');
    while(isdigit(c))r=(r<<1)+(r<<3)+(c^48),c=getchar();
    return f?-r:r;
}

int a,b,c,d;

inline void work(){
    a=read(),b=read(),c=read(),d=read();
    if(a>1ll*b*c)return (void)puts("-1");
    if(c<=d)return (void)printf("%d\n",a);
    int l=0,r=(c+d-1)/d+1;
    while(l+1<r){
        int mid=(l+r)>>1;
        if(a>=1ll*d*b*(mid-1))l=mid;
        else r=mid;
    }
    printf("%lld\n",1ll*a*l-1ll*d*b*(l-1)*l/2);
}

int main(){
    int t=read();
    while(t--)work();
    return 0;
}

 

posted @ 2020-10-26 08:21  一叶知秋‘  阅读(142)  评论(0编辑  收藏  举报