zoukankan      html  css  js  c++  java
  • CF1413 (Div.2)

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

    $ ext{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;
    }

    $ ext{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;
    }

    $ ext{C}$

    考试的时候双指针写挂了,就写了一个 $O(nlogn imes log10^9 imes 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
    ",r);
        return 0;
    }

    $ ext{D}$

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

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

    然后就发现 $ ext{WA}   ext{on}   ext{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;
    }

    $ ext{E}$

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

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

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

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

    然后最后答案就是 $tim imes a - b imes d imes 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
    ",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
    ",1ll*a*l-1ll*d*b*(l-1)*l/2);
    }
    
    int main(){
        int t=read();
        while(t--)work();
        return 0;
    }
  • 相关阅读:
    求连续子数组的最大和
    【LeetCode练习题】Gas Station
    再来看看快速排序
    【LeetCode练习题】First Missing Positive
    【LeetCode练习题】Merge Sorted Array
    Hdu 2089-不要62 数位dp
    Tsinsen A1517. 动态树 树链剖分,线段树,子树操作
    Bzoj 3505: [Cqoi2014]数三角形 数论
    Poj 3695-Rectangles 矩形切割
    Tsinsen A1505. 树(张闻涛) 倍增LCA,可持久化线段树,DFS序
  • 原文地址:https://www.cnblogs.com/wyzwyz/p/13876617.html
Copyright © 2011-2022 走看看