zoukankan      html  css  js  c++  java
  • 牛客多校第二场补题

    D-Duration

    签到



    F-Fake Maxpooling

    先得求lcm矩阵

    关于求(lcm)矩阵,一种方法是直接暴力枚举每一对((i,j)),然后暴力计算(gcd(i,j),lcm(i,j)=i*j/gcd(i,j))

    第二种是类似埃氏筛的思想,对于每一对互质的((i,j)),都去从1枚举一个k使得(i*k<=n) 并且 (j*k<=m),然后把每一对((i*k,j*k))的gcd标记为k,这样筛的效率就很高了(接近线性)

    最后得到lcm矩阵的复杂度就是(O(nm)),剩下就是求每个k*k的正子矩阵的最大值了

    由于是区间最大值,两次滑动窗口即可(这个题stldeque没被卡)

    #pragma GCC optimize(2)
    #include<bits/stdc++.h>
    #define ll long long
    #define fastio ios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
    using namespace std;
    double pi = acos(-1);
    const double eps = 1e-9;
    const int inf = 1e9 + 7;
    const int maxn = 5005;
     
    int DP[maxn][maxn];
    int A[maxn][maxn];
     
    struct poi
    {
        int id;
        ll num;
    };
     
    deque<poi>deq;
     
    int __gcd(int a, int b)
    {
        while (b)
        {
            ll tmp = b;
            b = a % b;
            a = tmp;
        }
        return a;
    }
     
     
    int main()
    {
        int n, m, k;
        scanf("%d%d%d", &n, &m, &k);
        for (int i = 1; i <= n; i++)
            for (int j = 1; j <= m; j++)
            {
                if (!DP[i][j])
                    for (int u = 1; u * i <= n && u * j <= m; u++)
                        DP[u * i][u * j] = u, A[u * i][u * j] = i * j * u;
            }
     
        for (int i = 1; i <= n; i++)
        {
            deq.clear();
            int j = 1;
            for (int j = 1; j <= m; ++j)
            {
                int tmp = A[i][j];
                while (!deq.empty() && deq.front().id <= j - k)deq.pop_front();
                while (!deq.empty() && tmp > deq.back().num)
                    deq.pop_back();
                deq.push_back({ j,tmp });
                DP[i][j] = deq.front().num;
            }
        }
        ll ans = 0;
        for (int j = k; j <= m; ++j)
        {
            deq.clear();
            for (int i = 1; i <= n; ++i)
            {
                int tmp = DP[i][j];
                while (!deq.empty() && deq.front().id <= i - k)deq.pop_front();
                while (!deq.empty() && tmp > deq.back().num)
                    deq.pop_back();
                deq.push_back({ i,tmp });
                if (i >= k)
                    ans += deq.front().num;
            }
        }
        printf("%lld
    ", ans);
     
        return 0;
     
    }
    


    C-Cover the Tree

    比赛的时候有思路,忘记写了

    先记录入度为1的点计数为sum,ans就是点数/2上取整;然后从入度不为1的点开始dfs,把每个入度为1的点的dfs记录下来,把i和sum / 2 + i连接起来就可以将所有的边覆盖(不太会证。。。画图举例吧)

    #pragma GCC optimize(2)
    #include<bits/stdc++.h>
    //#include<cstdio>
    //#include<iostream>
    //#include<vector>
    //#include<cstring>
    //#include<string>
    //#include<algorithm>
    #define ll long long
    #define fastio {ios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);};
    using namespace std;
    double pi = acos(-1);
    const double eps = 1e-9;
    const int inf = 1e9 + 7;
    const int maxn = 1e6 + 10;
    const ll mod = 998244353;
    
    vector<int>G[maxn];
    int sum = 0;
    int n;
    vector<int>xu;
    
    void dfs(int from, int last)
    {
    	if (G[from].size() == 1)
    	{
    		xu.push_back(from);
    		return;
    	}
    	for (int i = 0; i < G[from].size(); i++)
    	{
    		int to = G[from][i];
    		if (to != last)
    			dfs(to, from);
    	}
    }
    
    int main()
    {
    	fastio;
    	cin >> n;
    	for (int i = 1; i < n; i++)
    	{
    		int a, b;
    		cin >> a >> b;
    		G[a].push_back(b);
    		G[b].push_back(a);
    	}
    
    	for (int i = 1; i <= n; i++)
    		if (G[i].size() == 1)
    			sum++;
    	cout << (sum + 1) / 2 << endl;
    	for (int i = 1; i <= n; i++)
    		if (G[i].size() != 1)
    		{
    			dfs(i, -1);
    			break;
    		}
    	for (int i = 0; i < sum / 2; i++)
    		cout << xu[i] << " " << xu[sum - i - 1] << endl;
    	if (sum & 1)
    		cout << xu[sum / 2 ] << " " << xu[0] << endl;
    	return 0;
    }
    


    B-Boundary

    计算几何,枚举每一个点i,得到与圆心连线所对的弦对应的弧,利用同弧所对的圆周角相同,再去枚举另一个点j,将∠oji存下来,其中的众数就是ans

    #pragma GCC optimize(2)
    #include<bits/stdc++.h>
    #define ll long long
    #define fastio ios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
    using namespace std;
    double pi = acos(-1);
    const double eps = 1e-12;
    const int inf = 1e9 + 7;
    const int maxn = 2e5 + 10;
    
    int read()
    {
        int x = 0, f = 1;
        char c = getchar();
        while (c < '0' || c>'9') { if (c == '-') f = -1; c = getchar(); }
        while (c >= '0' && c <= '9') x = (x << 1) + (x << 3) + c - '0', c = getchar();
        return f * x;
    }
    
    
    inline int dcmp(double x)//cmp x with 0
    {
        if (fabs(x) <= eps)return 0;
        return x < 0 ? -1 : 1;
    }
    inline int cmp(double x, double y)
    {
        //x>y return 1
        //x<y reutrn -1
        //x==y return 0
        return dcmp(x - y);
    }
    
    double max(double x, double y)
    {
        return dcmp(x - y) > 0 ? x : y;
    }
    double min(double x, double y)
    {
        return dcmp(x - y) < 0 ? x : y;
    }
    
    struct Point {
        double x, y;
        Point() {}
        Point(double xx, double yy) { x = xx; y = yy; }
        Point operator -(Point s) { return Point(x - s.x, y - s.y); }
        Point operator +(Point s) { return Point(x + s.x, y + s.y); }
        double operator *(Point s) { return x * s.x + y * s.y; }
        double operator ^(Point s) { return x * s.y - y * s.x; }
    }p[2010];
    
    double len(Point a) { return sqrt(a * a); }
    double dis(Point a, Point b) { return len(b - a); }//两点之间的距离
    
    double cross(Point a, Point b, Point c)//叉乘,a为公共点
    {
        return (b - a) ^ (c - a);
    }
    double dot(Point a, Point b, Point c)//点乘 ,a为公共点
    {
        return (b - a) * (c - a);
    }
    
    double angle(Point a, Point b, Point c)//求两个向量的夹角(余弦定理),a为公共点 
    {
        return acos(dot(a, b, c) / dis(b, a) / dis(c, a));
    }
    
    bool Cmp(double x, double y)
    {
        if (cmp(x, y) == -1)return 1;
        return 0;
    }
    
    vector<double>rad;
    
    int main()
    {
        int n;
        scanf("%d", &n);
        for (int i = 1; i <= n; i++)
        {
            double x, y;
            scanf("%lf %lf", &x, &y);
            p[i] = { x,y };
        }
        if (n == 1)
        {
            printf("1
    ");
            return 0;
        }
        Point O = { 0.0,0.0 };
        int ans = 1;
        for (int i = 1; i <= n; i++)
        {
            rad.clear();
            for (int j = 1; j <= n; j++)
            {
                if (cross(O, p[i], p[j]) < 0)
                    rad.push_back(dot(p[j], O, p[i]) / (dis(p[j], p[i]) * dis(p[j], O)));
            }
            sort(rad.begin(), rad.end(), Cmp);
            int size = rad.size();
            for (int l = 0, r; l < size; l = r)
            {
                for (r = l; r < size && cmp(rad[l], rad[r]) == 0; r++);
                ans = max(ans, r - l + 1);
            }
        }
        printf("%d
    ", ans);
        return 0;
    
    }
    
  • 相关阅读:
    小白的基金理财课
    Spring Security 入门原理及实战
    spring-data-rest的魔力 10分钟实现增删改查
    redis单点、redis主从、redis哨兵sentinel,redis集群cluster配置搭建与使用
    Netty开发redis客户端,Netty发送redis命令,netty解析redis消息
    使用Netty实现HTTP服务器
    Netty实现心跳机制
    SpringMVC是怎么工作的,SpringMVC的工作原理
    Netty 学习系列
    Mybatis 源码学习系列
  • 原文地址:https://www.cnblogs.com/ruanbaiQAQ/p/13340085.html
Copyright © 2011-2022 走看看