zoukankan      html  css  js  c++  java
  • 新疆大学ACM新生赛(公开赛)

    A hello world

    签到

    #include<bits/stdc++.h>
    using namespace std;
    
    string s="hello world";
    int main(){
        for(int i=0;i<s.size();i++){
            cout<<char(s[i]+1);
        }
    }
    

    B 挂科

    简单想一想就好了

    #include<bits/stdc++.h>
    
    using namespace std;
    
    int main(){
        int n,x,y;
        cin>>n>>x>>y;
        cout<<min(x,y)<<" "<<max(0,x+y-n)<<endl;
    }
    

    C a+b

    签到

    #include<bits/stdc++.h>
    
    using namespace std;
    
    int main(){
        int a,b;
        cin>>a>>b;
        printf("%x",a+b);
    }
    

    D 数组的和

    维护一下前缀和,然后扫一下即可

    #include<bits/stdc++.h>
    
    using namespace std;
    const int N = 2e5+5;
    
    long long pre[N],res=0;
    int main(){
        int n,k;
        cin>>n>>k;
        for(int i=1;i<=n;i++){
            long long x;
            cin>>x;
            pre[i]=pre[i-1]+x;
            if(i>=k){
                res=max(pre[i]-pre[i-k],res);
            }
        }
        cout<<pre[n]-res<<endl;
    }
    

    E 异或

    题目描述:

    给定一个长度为n初始全为0的数列ai,下标从1开始。定义操作模k异或v为对所有满足(i≡0(modk))的下标i,将异或上整数v(即令$ai=ai⊕v $)。

    给出q次操作,每次操作之后输出序列的异或和,并且在操作结束之后输出整个序列。

    思路:

    对于所有输入,首先开一个数组维护所有模k的数需要异或的异或和,最后遍历(a_i),找出所有(a_i)的约数,异或上之前维护的这个异或和即可,复杂度为(O(n*sqrt{n}))

    #include<bits/stdc++.h>
    
    using namespace std;
    
    const int N = 1e6 + 5;
    typedef long long LL;
    
    int mp[N], a[N], n, q, k, v;
    
    vector<int> get_divisors(int x) {
        vector<int> res;  // 记录答案
        for (int i = 1; i <= x /i; ++i) {  // 枚举到sqrtx(x)
            if (x % i == 0) {  // 如果能够整除
                res.push_back(i);  // 放入i
                if (i != x / i) res.push_back(x / i);  // x/i不等于i,也放入答案中
            }
        }
        return res;
    }
    
    int main(){
        cin >> n >> q;
        int sum = 0;
        for (int i = 1; i <= q; ++i) {
            scanf("%d%d", &k, &v);
            int cnt = n / k;
            if (cnt & 1) sum ^=v;
            printf("%d
    ", sum);
            if (k > n) continue;
            mp[k] ^= v;
        }
        for (int i = 1; i <= n; ++i) {
            vector<int> tmp = get_divisors(i);
            for (int j = 0; j < tmp.size(); ++j) a[i] ^= mp[tmp[j]];
        }
        for (int i = 1; i <= n; ++i)
            printf("%d ", a[i]);
            return 0;
    }
    

    F 最近的两个点

    题目描述:

    给定三维空间上n个点,每个点都有xi,yi,zi三个坐标值.找出其中的一对点的距离,使得在这n个点的所有点对中,该距离为所有点对中最小的.

    思路:

    分治法,首先来看二维平面内最近的两个点问题。

    现将所有的点按照X坐标排序,然后取中点,将其分为两个部分:

    对于最近的点对,只可能有三种情况:

    1.两个点都在左区间

    2.两个点都在右区间

    3.两个点分局mid的左右两侧

    对于左右两个区间,我们可以通过分治的方法求出这个区间内的最近点对的距离,那么这时我们得到了(res=min(solve(l,mid),solve(mid+1,r)))

    第三种情况怎么处理呢?因为我们已经得到了res代表两个区间中最近点对的距离,所以如果存在第三种情况,那么其x值必然在([mid-res,mid+res])之间,那么和他配对的点在哪呢?必然是以这个点为圆心,以res为半径画圆,只需要考虑这个圆内的点即可,经过下面的推导可以证明最多只有6个点可以何其配对,这样我们第三种情况在(O(n))的复杂度内就可以解决

    证明最多只有6个点可以配对:

    首先考虑极端情况,即该点正好在分界线 mid 上:

    因为圆形难以分析,我们直接放缩到橙色矩形的情况,将矩形划分为6个部分,假设左侧有7个点位于橙色矩形内,那么根据抽屉原理,必然有两个点放在同一个小矩形内,而同一个小矩形内的点,其距离最大值为对角线距离即(r*sqrt{(2/3)^2+(1/2)^2}=5/6*r<r),也就是说这两个点的距离已经比当前求出的最小距离要小了,所以不可能有7个点,最多有6个点,所以我们直接将([mid-res,mid+res])内的点根据y值排序,然后枚举每个点,由于最多只有6个点能和当前枚举的点进行配对,所以枚举每个点进行更新的复杂度为(O(6*n))(O(n))

    那么三维的怎么做呢?

    因为分治的时候只是用了x作为分治的边界,跟y和x没有什么关系,所以直接在枚举的时候加上z的约束即可,其他都可以照抄~

    #include<bits/stdc++.h>
    
    using namespace std;
    
    const int N = 1e5 + 5;
    int n;
    const double INF = 0x3f3f3f3f;
    struct node
    {
        double x, y, z;
    }a[N];
    
    bool cmpx(node a,node b){
        return a.x < b.x;
    }
    
    bool cmpy(node a,node b){
        return a.y < b.y;
    }
    
    double dis(node a,node b){
        return (sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y) + (a.z - b.z) * (a.z - b.z)));
    }
    
    double solve(int l,int r){
        if(l==r){
            return INF;    //当前区间只有一个点,返回INF,避免更新答案
        }
        int mid = l + r >> 1;   
        double midnum = a[mid].x;   //区间中点
        double res = min(solve(l, mid), solve(mid + 1, r));  //分治求两边区间的最小距离
        sort(a + l, a + r + 1, cmpy);      //按照y轴排序,这样后面在找的时候只需要找最近的几个点即可
        int temp[N], cnt = 0;
        for (int i = l; i <= r; i++){
            if(a[i].x>=midnum-res&&a[i].x<=midnum+res){
                temp[cnt++] = i;     //将“中间地带”的点加入temp,准备判断
            }
        }
        for (int i = 0; i < cnt;i++){
            for (int j = i - 1; j >= 0 && (a[temp[i]].y - a[temp[j]].y < res) && (a[temp[i]].z - a[temp[j]].z < res);j--)  //因为已经排好序了,所以只会遍历到最近的几个点,可以证明最多只有6个点,所以复杂度为O(n)
            {
                res = min(res, dis(a[temp[i]], a[temp[j]]));
            }
        }
        return res;
    }
    
    int main(){
        cin>>n;
        for (int i = 0; i < n;i++){
            cin >> a[i].x >> a[i].y >> a[i].z;
        }
        sort(a, a + n, cmpx);
        printf("%.3lf
    ",solve(0, n - 1));
        return 0;
    }
    

    参考:

    https://www.acwing.com/solution/content/15774/

  • 相关阅读:
    JSON 字符串 与 java 对象的转换
    DNS解析过程详解
    全面了解移动端DNS域名劫持等杂症:原理、根源、HttpDNS解决方案等
    TCP Send函数的阻塞和非阻塞,以及TCP发送数据的异常情况
    基于TCP协议的应用层的ACK机制
    Golang的反射reflect深入理解和示例
    C/C++中struct中内存对齐规则
    Go 包依赖管理工具 —— govendor
    什么是幂等?什么情况下需要考虑幂等?怎么解决幂等的问题?
    Golang 中间件简介 MiddleWare
  • 原文地址:https://www.cnblogs.com/dyhaohaoxuexi/p/14028260.html
Copyright © 2011-2022 走看看