• Codeforces 817


    A

    你可以按如下方式移动

    问能不能从给定的一个坐标走到另一个。

    【solution】

    裸,奇偶性注意

    #include<stdio.h>
    #include<stdlib.h>
    #include<iostream>
    #include<string>
    #include<string.h>
    #include<algorithm>
    #include<math.h>
    #include<queue>
    #include<map>
    #include<vector>
    #include<set>
    #define il inline
    #define re register
    using namespace std;
    int a1,b1,a2,b2,x,y,a,b;
    int main(){
        cin>>a1>>b1>>a2>>b2>>x>>y;
        if((a1-a2)%x==0&&(b1-b2)%y==0){
            a=(a1-a2)/x;
            b=(b1-b2)/y;
            if((a-b)%2==0){
                cout<<"YES
    ";
            }
            else cout<<"NO
    ";
        }
        else cout<<"NO
    ";
        return 0;
    }

    B

    After returning from the army Makes received a gift — an array a consisting of n positive integer numbers. He hadn't been solving problems for a long time, so he became interested to answer a particular question: how many triples of indices (i,  j,  k) (i < j < k), such that ai·aj·ak is minimum possible, are there in the array? Help him with it!

    Input

    The first line of input contains a positive integer number n (3 ≤ n ≤ 105) — the number of elements in array a. The second line contains n positive integer numbers ai (1 ≤ ai ≤ 109) — the elements of a given array.

    Output

    Print one number — the quantity of triples (i,  j,  k) such that i,  j and k are pairwise distinct and ai·aj·ak is minimum possible.

    【solution】

    就是问成绩最小的有序三元组有多少个,排序搞定 

    #include<stdio.h>
    #include<stdlib.h>
    #include<iostream>
    #include<string>
    #include<string.h>
    #include<algorithm>
    #include<math.h>
    #include<queue>
    #include<map>
    #include<vector>
    #include<set>
    #define il inline
    #define re register
    using namespace std;
    typedef long long ll;
    const int N=1000001;
    int n,a[N],b[N],c[N],m;
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);b[i]=a[i];
        }
        sort(b+1,b+n+1);
        m=unique(b+1,b+n+1)-b-1;
        for(int i=1;i<=n;i++)
            a[i]=lower_bound(b+1,b+m+1,a[i])-b;
        for(int i=1;i<=n;i++) c[a[i]]++;
        if(c[1]>=3){
            cout<<((ll)c[1]*(c[1]-1)*(c[1]-2)/6)<<endl;
        }
        else{
            if(c[1]==2){
                cout<<c[2]<<endl;
            }
            else if(c[1]==1){
                if(c[2]>=2) cout<<((ll)c[2]*(c[2]-1)/2)<<endl;
                else cout<<c[3]<<endl;
            }
        }
        return 0;
    }

    C

    f(i)表示i所有数位的和

    问满足 i-f(i)>=s  (i<=n) 的有多少个

    n,s<=10^18

    【solution】

    显而易见,f(i)最大也就是18*9=162,所以[s,s+1000]这个范围直接枚举,更大的肯定是满足的。

    #include<stdio.h>
    #include<stdlib.h>
    #include<iostream>
    #include<string>
    #include<string.h>
    #include<algorithm>
    #include<math.h>
    #include<queue>
    #include<map>
    #include<vector>
    #include<set>
    #define il inline
    #define re register
    using namespace std;
    typedef long long ll;
    ll n,m,ans;
    il ll f(ll n){
        ll res=0;
        for(;n;n/=10)
            res+=(n%10);
        return res;
    }
    int main(){
        cin>>n>>m;
        for(ll i=m;i<=n&&i<=m+10000;i++){
            if(i-f(i)>=m) ans++;
        }
        ans+=n-min(n,m+10000);
        cout<<ans;
        return 0;
    }

    D

    给定一个长度为n的数组a (n<=100000)

    求sigma(max(i,j)-min(i,j)) (1<=i<=j<=n)

    【solution】

    显然的把最大和最小拆开做

    我们采用分治算法解决问题

    我们去除一段中最大(小)统计贡献,然后左右递归

    最多递归n次,采用st算法加速

    #include<stdio.h>
    #include<stdlib.h>
    #include<iostream>
    #include<string>
    #include<string.h>
    #include<algorithm>
    #include<math.h>
    #include<queue>
    #include<map>
    #include<vector>
    #include<set>
    #define il inline
    #define re register
    #define cmin(x,y) (a[x]<a[y]?x:y)
    #define cmax(x,y) (a[x]>a[y]?x:y) 
    using namespace std;
    typedef long long ll;
    const int N=1111111;
    int n,s[N][21],t[N][21],a[N],k[N];
    ll ans=0;
    il int getmin(int l,int r){
        int h=r-l+1,p=r-(1<<k[h])+1;
        return cmin(s[l][k[h]],s[p][k[h]]);
    }
    il int getmax(int l,int r){
        int h=r-l+1,p=r-(1<<k[h])+1;
        return cmax(t[l][k[h]],t[p][k[h]]);
    }
    il void dfs1(int l,int r){
        if(l>r) return;
        int mid=getmin(l,r);
        ans-=(ll)a[mid]*(mid-l+1)*(r-mid+1);
        dfs1(l,mid-1);dfs1(mid+1,r);
    }
    il void dfs2(int l,int r){
        if(l>r) return;
        int mid=getmax(l,r);
        ans+=(ll)a[mid]*(mid-l+1)*(r-mid+1);
        dfs2(l,mid-1);dfs2(mid+1,r);
    }
    int main(){
        scanf("%d",&n);
        for(int i=1,K=0;i<=n;i++){
            if((1<<K+1)<i) K++;
            scanf("%d",&a[i]);k[i]=K;
            t[i][0]=s[i][0]=i;
        }
        for(int j=1;j<=k[n];j++){
            for(int i=1,k=(1<<j-1)+1;k<=n;i++,k++){
                s[i][j]=cmin(s[i][j-1],s[k][j-1]);
                t[i][j]=cmax(t[i][j-1],t[k][j-1]);
            }
        }
        dfs1(1,n);dfs2(1,n);
        cout<<ans;
        return 0;
    }

    E

    维护一个正整数构成的集合p

    支持三个操作

    1、添加一个元素

    2、删除一个已经存在的元素

    3、输入x,y,询问集合中满足pi^x<y的元素有多少个。

    【solution】

    解法十分的巧妙,把元素转化成二进制,建立trie树,问题迎刃而解。

    希望这种做法能在难题里得到应用。

    #include<stdio.h>
    #include<stdlib.h>
    #include<iostream>
    #include<string>
    #include<string.h>
    #include<algorithm>
    #include<math.h>
    #include<queue>
    #include<map>
    #include<vector>
    #include<set>
    #define il inline
    #define re register
    using namespace std;
    const int N=1000001;
    int n=1,Q,c[N*10][2],s[N*10];
    int main(){
        scanf("%d",&Q);
        for(int ii=1,jj,x,y,h,ans;ii<=Q;ii++){
            scanf("%d%d",&jj,&x);h=1;
            if(jj==1){
                for(int i=30,j;i>=0;i--){
                    j=(x&(1<<i))>0;
                    if(!c[h][j]) c[h][j]=(++n);
                    h=c[h][j];s[h]++;
                }
            }
            if(jj==2){
                for(int i=30,j;i>=0;i--){
                    j=(x&(1<<i))>0;
                    h=c[h][j];s[h]--;
                }
            }
            if(jj==3){
                scanf("%d",&y);ans=0;
                for(int i=30;i>=0;i--){
                    if(y&(1<<i)){
                        if(x&(1<<i)){
                            ans+=s[c[h][1]];
                            h=c[h][0];
                        }
                        else{
                            ans+=s[c[h][0]];
                            h=c[h][1];
                        }
                    }
                    else{
                        if(x&(1<<i)) h=c[h][1];
                        else h=c[h][0];
                    }
                }
                printf("%d
    ",ans);
            }
        }
        return 0;
    }

    F

    维护区间裸题

    1、染黑一个区间

    2、染白一个区间

    3、翻转一个区间

    操作后要求输出最靠左的黑点的坐标

    【solution】

    线段树

    细节:有的标记不能简单覆盖!【以前一直忽略的!】

    #include<stdio.h>
    #include<stdlib.h>
    #include<iostream>
    #include<string>
    #include<string.h>
    #include<algorithm>
    #include<math.h>
    #include<queue>
    #include<map>
    #include<vector>
    #include<set>
    #define il inline
    #define re register
    using namespace std;
    typedef long long ll;
    const int N=2000001;
    int t[N],Q,m=1,L[N],R[N],s[N],p,c[N];
    ll l[N],r[N],b[N];
    il int d(int a,int b){
        if(a==0) return b;
        if(b<3) return b;
        return 3-a;
    }
    il void pushdown(int i){
        if(t[i]==0) return;
        if(t[i]==1){
            t[i+i]=t[i+i+1]=1;
            s[i+i]=R[i+i]-L[i+i]+1;
            s[i+i+1]=R[i+i+1]-L[i+i+1]+1;
            t[i]=0;
        }
        else if(t[i]==2){
            t[i+i]=t[i+i+1]=2;
            s[i+i]=s[i+i+1]=0;
            t[i]=0;
        }
        else if(t[i]==3){
            t[i+i]=d(t[i+i],t[i]);
            t[i+i+1]=d(t[i+i+1],t[i]);
            s[i+i]=R[i+i]-L[i+i]+1-s[i+i];
            s[i+i+1]=R[i+i+1]-L[i+i+1]+1-s[i+i+1];
            t[i]=0;
        }
    }
    il void work(int i,int p,int q,int v){
        if(q<L[i]||p>R[i]) return;
        if(i<m) pushdown(i);
        if(p<=L[i]&&R[i]<=q){
            if(v==1) s[i]=R[i]-L[i]+1;
            if(v==2) s[i]=0;
            if(v==3) s[i]=R[i]-L[i]+1-s[i];
            t[i]=d(t[i],v);
            return;
        }
        work(i+i,p,q,v);work(i+i+1,p,q,v);
        s[i]=s[i+i]+s[i+i+1];
    }
    il int query(int i){
        if(i<m) pushdown(i);
        if(s[i]==0) return L[i];
        if(s[i+i]<R[i+i]-L[i+i]+1) return query(i+i);
        else return query(i+i+1);
    }
    int main(){
        scanf("%d",&Q);
        for(int i=1;i<=Q;i++){
            scanf("%d%I64d%I64d",&c[i],&l[i],&r[i]);
            b[++p]=l[i];b[++p]=l[i]+1;
            b[++p]=r[i];b[++p]=r[i]+1;
        }
        b[++p]=1;    
        sort(b+1,b+p+1);
        p=unique(b+1,b+p+1)-b-1;
        for(int i=1;i<=Q;i++){
            l[i]=lower_bound(b+1,b+p+1,l[i])-b;
            r[i]=lower_bound(b+1,b+p+1,r[i])-b;
        }
        while(m<p) m<<=1;
        for(int i=m;i<m+m;i++)
            L[i]=R[i]=i-m+1;
        for(int i=m-1;i;i--)
            L[i]=L[i+i],R[i]=R[i+i+1];
        for(int i=1;i<=Q;i++){
            work(1,l[i],r[i],c[i]);
            printf("%I64d
    ",b[query(1)]);
        }
        return 0;
    }
  • 相关阅读:
    使用wchar_t输入,显示中文
    MFC使用rich edit若干问题
    一种对话框嵌入MFC 文档结构效果的实现方法(一),让你的自定义对话框区域同客户区大小一起改变
    一种在MFC程序上显示jpeg图片的方法(二)曙光乍现
    一种在MFC程序上显示jpeg图片的方法(一)宁滥勿缺
    MFC---GDI之DC类杂记,以画尺子为例
    又让厂公着半天急----一例自定义MFC程序编译时LNK2019错误
    egret 引擎分析之三————egret make --egretversion xxxx 到底做了什么?
    egret 引擎分析之二————从selector.js说起
    egret 引擎分析之一————egret 命令的时候发生了什么
  • 原文地址:https://www.cnblogs.com/ExiledPoet/p/7030674.html
Copyright © 2020-2023  润新知