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\n";
        }
        else cout<<"NO\n";
    }
    else cout<<"NO\n";
    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][2],s[N];
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\n",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\n",b[query(1)]);
    }
    return 0;
}
时间: 2024-08-11 07:38:22

Codeforces 817的相关文章

Codeforces 817+818(A~C)

(点击题目即可查看原题) 817A Treasure Hunt 题意:给出起点和终点,每次移动只能从 (a,b)移动至(a+x,b+y) , (a+x,b-y) , (a-x,b+y) , (a-x,b-y) 四个位置,问能否从终点走到起点 思路:先计算出起点和终点的横纵坐标之差 X,Y, 首先必须满足 X%x == 0 && Y % y == 0 ,这样才可以走到和终点一样的位置,后计算 X/x . Y/y ,我们注意到如果 X/x != Y/y 那么就可能无法用到达,不过,我们可以在两

【codeforces 718E】E. Matvey&#39;s Birthday

题目大意&链接: http://codeforces.com/problemset/problem/718/E 给一个长为n(n<=100 000)的只包含‘a’~‘h’8个字符的字符串s.两个位置i,j(i!=j)存在一条边,当且仅当|i-j|==1或s[i]==s[j].求这个无向图的直径,以及直径数量. 题解:  命题1:任意位置之间距离不会大于15. 证明:对于任意两个位置i,j之间,其所经过每种字符不会超过2个(因为相同字符会连边),所以i,j经过节点至多为16,也就意味着边数至多

Codeforces 124A - The number of positions

题目链接:http://codeforces.com/problemset/problem/124/A Petr stands in line of n people, but he doesn't know exactly which position he occupies. He can say that there are no less than a people standing in front of him and no more than b people standing b

Codeforces 841D Leha and another game about graph - 差分

Leha plays a computer game, where is on each level is given a connected graph with n vertices and m edges. Graph can contain multiple edges, but can not contain self loops. Each vertex has an integer di, which can be equal to 0, 1 or  - 1. To pass th

Codeforces Round #286 (Div. 1) A. Mr. Kitayuta, the Treasure Hunter DP

链接: http://codeforces.com/problemset/problem/506/A 题意: 给出30000个岛,有n个宝石分布在上面,第一步到d位置,每次走的距离与上一步的差距不大于1,问走完一路最多捡到多少块宝石. 题解: 容易想到DP,dp[i][j]表示到达 i 处,现在步长为 j 时最多收集到的财富,转移也不难,cnt[i]表示 i 处的财富. dp[i+step-1] = max(dp[i+step-1],dp[i][j]+cnt[i+step+1]) dp[i+st

Codeforces 772A Voltage Keepsake - 二分答案

You have n devices that you want to use simultaneously. The i-th device uses ai units of power per second. This usage is continuous. That is, in λ seconds, the device will use λ·ai units of power. The i-th device currently has bi units of power store

Educational Codeforces Round 21 G. Anthem of Berland(dp+kmp)

题目链接:Educational Codeforces Round 21 G. Anthem of Berland 题意: 给你两个字符串,第一个字符串包含问号,问号可以变成任意字符串. 问你第一个字符串最多包含多少个第二个字符串. 题解: 考虑dp[i][j],表示当前考虑到第一个串的第i位,已经匹配到第二个字符串的第j位. 这样的话复杂度为26*n*m*O(fail). fail可以用kmp进行预处理,将26个字母全部处理出来,这样复杂度就变成了26*n*m. 状态转移看代码(就是一个kmp

Codeforces Round #408 (Div. 2) B

Description Zane the wizard is going to perform a magic show shuffling the cups. There are n cups, numbered from 1 to n, placed along the x-axis on a table that has m holes on it. More precisely, cup i is on the table at the position x?=?i. The probl

Codeforces 617 E. XOR and Favorite Number

题目链接:http://codeforces.com/problemset/problem/617/E 一看这种区间查询的题目,考虑一下莫队. 如何${O(1)}$的修改和查询呢? 令${f(i,j)}$表示区间${\left [ l,r \right ]}$内数字的异或和. 那么:${f(l,r)=f(1,r)~~xor~~f(1,l-1)=k}$ 记一下前缀异或和即可维护. 1 #include<iostream> 2 #include<cstdio> 3 #include&l