• 2017-2018 ACM-ICPC Northern Eurasia (Northeastern European Regional) Contest (NEERC 17) 日常训练


    A - Archery Tournament

    题目大意:按时间顺序出现靶子和射击一个位置,靶子的圆心为(x, y)半径为r,即圆与x轴相切,靶子不会重叠,靶子被击中后消失,

    每次射击找出哪个靶子被射中,或者没有射中靶子。

    思路:关键点在于,圆都与x轴相切,那么我们能发现,如果射击在(x, y) 这个点,包含它的圆只可能是它左边第一个直径>= y的圆c1,

    或者是它右边第一个直径 >=y 的圆c2,因为在c1 和 c2之间的圆不可能覆盖到(x, y), 因为它们的直径小于y,在c1左边和c2右边的圆

    通过画图我们也能得出不肯能包含(x, y),那么每次射击我们只需要check两个圆就好了。

    找圆的过程能用线段树维护,加入一个圆就在线段树对应的x的位置的值变成2*r,然后通过二分用线段树找圆,最后判一下是否在圆内。

    #include<bits/stdc++.h>
    #define LL long long
    #define fi first
    #define se second
    #define mk make_pair
    #define pii pair<int, int>
    
    using namespace std;
    
    const int N = 2e5 + 7;
    const int M = 1e5 + 7;
    const int inf = 0x3f3f3f3f;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const int mod = 1e9 +7;
    
    
    int n, tot, mx[N << 2], X[N], hs[N];
    
    struct Qus {
        int op, x, y;
    } qus[N];
    
    void update(int pos, int v, int l, int r, int rt) {
        if(l == r) {
            mx[rt] = v;
            return;
        }
    
        int mid = l + r >> 1;
        if(pos <= mid) update(pos, v, l, mid, rt << 1);
        else update(pos, v, mid + 1, r, rt << 1 | 1);
    
        mx[rt] = max(mx[rt << 1], mx[rt << 1 | 1]);
    }
    
    int getMx(int L, int R, int l, int r, int rt) {
        if(l >= L && r <= R) return mx[rt];
    
        int mid = l + r >> 1, ans = 0;
    
        if(L <= mid) ans = max(ans, getMx(L, R, l, mid, rt << 1));
        if(R > mid) ans = max(ans, getMx(L, R, mid + 1, r, rt << 1 | 1));
        return ans;
    }
    
    bool check(int x, int y, int id) {
        LL dis1 = 1ll * qus[id].y * qus[id].y;
        LL dis2 = 1ll * (x - qus[id].x) * (x - qus[id].x) + 1ll * (y - qus[id].y) * (y - qus[id].y);
        return dis1 > dis2;
    }
    
    int main() {
    
        scanf("%d", &n);
    
        for(int i = 1; i <= n; i++) {
            scanf("%d%d%d", &qus[i].op, &qus[i].x, &qus[i].y);
            hs[++tot] = qus[i].x;
        }
    
        sort(hs + 1, hs + 1 + tot);
        tot = unique(hs + 1, hs + 1 + tot) - hs - 1;
    
    
        for(int i = 1; i <= n; i++) {
            int op = qus[i].op, x = qus[i].x, y = qus[i].y;
    
            int pos = lower_bound(hs + 1, hs + 1 + tot, x) - hs;
    
            if(op == 1) {
                X[pos] = i;
                update(pos, 2 * y, 1, tot, 1);
            } else {
                int l = 1, r = pos, ret = -1;
                while(l <= r) {
                    int mid = l + r >> 1;
                    if(getMx(mid, pos, 1, tot, 1) >= y) ret = mid, l = mid + 1;
                    else r = mid - 1;
                }
    
                if(ret != -1 && check(x, y, X[ret])) {
                    printf("%d
    ", X[ret]);
                    update(ret, 0, 1, tot, 1);
                    continue;
                }
    
                l = pos, r = tot, ret = -1;
                while(l <= r) {
                    int mid = l + r >> 1;
                    if(getMx(pos, mid, 1, tot, 1) >= y) ret = mid, r = mid - 1;
                    else l = mid + 1;
                }
    
                if(ret != -1 && check(x, y, X[ret])) {
                    printf("%d
    ", X[ret]);
                    update(ret, 0, 1, tot, 1);
                    continue;
                }
    
                puts("-1");
    
            }
        }
        return 0;
    }
    View Code

    B - Box

    题目大意:问长宽高为a, b, c的立方体,能不能用n * m的纸折出来。

    思路:暴力枚举判断。。

    #include<bits/stdc++.h>
    #define LL long long
    #define fi first
    #define se second
    #define mk make_pair
    #define pii pair<int, int>
    
    using namespace std;
    
    const int N = 1000 + 7;
    const int M = 1e5 + 7;
    const int inf = 0x3f3f3f3f;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const int mod = 1e9 +7;
    
    
    int n, m, a[3], id[3];
    
    bool check(int x, int y) {
        if(x <= n && y <= m) return true;
        if(x <= m && y <= n) return true;
        return false;
    }
    int main() {
        scanf("%d%d%d", &a[0], &a[1], &a[2]);
        id[0] = 0, id[1] = 1, id[2] = 2;
        scanf("%d%d", &n, &m);
    
        sort(a, a + 3);
    
        do {
            int x = a[id[0]], y = a[id[1]], z = a[id[2]];
    
            if(check(2 * z + x, 2 * y + 2 * z)) {
                puts("Yes");
                return 0;
            }
    
            if(check(x + y + z, 2 * x + y + z)) {
                puts("Yes");
                return 0;
            }
    
            if(check(2 * z + x, x + 2 * y + z)) {
                puts("Yes");
                return 0;
            }
    
            if(check(3 * y + x + z, x + z)) {
                puts("Yes");
                return 0;
            }
        } while(next_permutation(id, id + 3));
        puts("No");
        return 0;
    }
    
    
    /*
    2z + x
    2y + 2z
    
    x + y + z
    2x + y + z
    
    2z + x
    x + 2y + z
    
    
    */
    View Code

    C - Connections

    题目大意:给你一个 n 个点 m (m >= 2 * n)条边的有向图,且原图为一个强连通分量,要求你选出2 * n条边,其他的删掉仍然是一个

    强连通分量。

    思路:比赛的时候我没想到,队友想出来的。。 用1号点跑一遍图,建反边用1号点再跑一次就好了。 应该挺听容易想到的,题目说2 * n

    应该想到由两个树组成。

    //#pragma comment(linker, "/stack:200000000")
    //#pragma GCC optimize("Ofast,no-stack-protector")
    //#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
    //#pragma GCC optimize("unroll-loops")
    #include<bits/stdc++.h>
    #define fi first
    #define se second
    #define mp make_pair
    #define pb push_back
    #define pi acos(-1.0)
    #define ll long long
    #define vi vector<int>
    #define mod 1000000007
    #define ld long double
    #define C 0.5772156649
    #define ls l,m,rt<<1
    #define rs m+1,r,rt<<1|1
    #define pil pair<int,ll>
    #define pli pair<ll,int>
    #define pii pair<int,int>
    #define cd complex<double>
    #define ull unsigned long long
    #define base 1000000000000000000
    #define fio ios::sync_with_stdio(false);cin.tie(0)
    
    using namespace std;
    
    const double eps=1e-6;
    const int N=100000+10,maxn=500000+10,inf=0x3f3f3f3f,INF=0x3f3f3f3f3f3f3f3f;
    
    vector<pair<int,int> >v[N],rev[N];
    pii p[N];
    bool vis[N],used[N];
    void dfs(int u)
    {
        vis[u]=1;
        for(int i=0;i<v[u].size();i++)
        {
            int x=v[u][i].fi;
            if(!vis[x])
            {
                used[v[u][i].se]=1;
                dfs(x);
            }
        }
    }
    void dfs1(int u)
    {
        vis[u]=1;
        for(int i=0;i<rev[u].size();i++)
        {
            int x=rev[u][i].fi;
            if(!vis[x])
            {
                used[rev[u][i].se]=1;
                dfs1(x);
            }
        }
    }
    int main()
    {
        int T;scanf("%d",&T);
        while(T--)
        {
            int n,m;
            scanf("%d%d",&n,&m);
            for(int i=1;i<=n;i++)v[i].clear(),rev[i].clear();
            for(int i=0;i<m;i++)
            {
                int x,y;
                scanf("%d%d",&x,&y);
                v[x].pb(mp(y,i));
                rev[y].pb(mp(x,i));
                p[i]=mp(x,y);
                used[i]=0;
            }
            memset(vis,0,sizeof vis);
            dfs(1);
            memset(vis,0,sizeof vis);
            dfs1(1);
            int sum=0;
            for(int i=0;i<m;i++)
                if(used[i])
                    sum++;
            int now=2*n-sum;
            for(int i=0;i<m;i++)
            {
                if(!used[i]&&now)
                {
                    now--;
                    used[i]=1;
                }
            }
            for(int i=0;i<m;i++)
                if(!used[i])
                    printf("%d %d
    ",p[i].fi,p[i].se);
        }
        return 0;
    }
    /********************
    
    ********************/
    View Code

    D - Designing the Toy

    题目大意:给你三视图的每个面能看见的方块个数a, b, c,然后构造出这样的图形。

    思路:一起想了挺久的,三维立体很难实现,我们就考虑把所有点放一个面里面,构成图形的个数就是max(a, b, c),

    斜着放三面个数都加一,横着放两面个数加一,填补空缺一个面加一,构造一下。细节挺多的。。。

    //#pragma comment(linker, "/stack:200000000")
    //#pragma GCC optimize("Ofast,no-stack-protector")
    //#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
    //#pragma GCC optimize("unroll-loops")
    #include<bits/stdc++.h>
    #define fi first
    #define se second
    #define mp make_pair
    #define pb push_back
    #define pi acos(-1.0)
    #define ll long long
    #define vi vector<int>
    #define mod 1000000007
    #define ld long double
    #define C 0.5772156649
    #define ls l,m,rt<<1
    #define rs m+1,r,rt<<1|1
    #define pil pair<int,ll>
    #define pli pair<ll,int>
    #define pii pair<int,int>
    #define cd complex<double>
    #define ull unsigned long long
    #define base 1000000000000000000
    #define fio ios::sync_with_stdio(false);cin.tie(0)
    
    using namespace std;
    
    const double eps=1e-6;
    const int N=100+10,maxn=500000+10,inf=0x3f3f3f3f,INF=0x3f3f3f3f3f3f3f3f;
    
    int a[3], b[3];
    
    struct point{
        int x,y,z;
    };
    int ok[N][N];
    void solve(int x,int y,int z){
        vector<point> v;
        vector<point> ans;
        for(int i=0;i<x;i++)
            v.pb({0,i,i});
        for(int i=x;i<y;i++)
            v.pb({0,x-1,i});
        for(int i=0;i<v.size();i++)ok[v[i].y][v[i].z]=1;
        int now=z-y;
        for(int i=0;i<x;i++)
        {
            for(int j=0;j<y;j++)
            {
                if(!ok[i][j]&&now)
                {
                    v.pb({0,i,j});
                    ok[i][j]=1;
                    now--;
                }
            }
        }
        if(now!=0){puts("-1");return ;}
        if(b[0]==a[0]&&b[1]==a[2]&&b[2]==a[1])
        {
            for(int i=0;i<v.size();i++)swap(v[i].x,v[i].y);
        }
        else if(b[0]==a[1]&&b[1]==a[0]&&b[2]==a[2])
        {
            for(int i=0;i<v.size();i++)swap(v[i].y,v[i].z);
        }
        else if(b[0]==a[1]&&b[1]==a[2]&&b[2]==a[0])
        {
            for(int i=0;i<v.size();i++)
            {
                swap(v[i].x,v[i].z);
                swap(v[i].y,v[i].z);
            }
        }
        else if(b[0]==a[2]&&b[1]==a[0]&&b[2]==a[1])
        {
            for(int i=0;i<v.size();i++)
            {
                swap(v[i].x,v[i].y);
                swap(v[i].y,v[i].z);
            }
        }
        else if(b[0]==a[2]&&b[1]==a[1]&&b[2]==a[0])
        {
            for(int i=0;i<v.size();i++)
            {
                swap(v[i].x,v[i].z);
            }
        }
        printf("%d
    ",v.size());
        for(int i=0;i<v.size();i++)
            printf("%d %d %d
    ",v[i].x,v[i].y,v[i].z);
    }
    int main(){
    
        for(int i = 0; i < 3; i++) {
            scanf("%d", &a[i]);
            b[i] = a[i];
        }
        sort(a, a + 3);
        solve(a[0],a[1],a[2]);
        return 0;
    }
    /********************
    
    ********************/
    View Code

    E - Easy Quest

    队友写的水题,不知道啥意思。

    //#pragma comment(linker, "/stack:200000000")
    //#pragma GCC optimize("Ofast,no-stack-protector")
    //#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
    //#pragma GCC optimize("unroll-loops")
    #include<bits/stdc++.h>
    #define fi first
    #define se second
    #define mp make_pair
    #define pb push_back
    #define pi acos(-1.0)
    #define ll long long
    #define vi vector<int>
    #define mod 1000000007
    #define ld long double
    #define C 0.5772156649
    #define ls l,m,rt<<1
    #define rs m+1,r,rt<<1|1
    #define pil pair<int,ll>
    #define pli pair<ll,int>
    #define pii pair<int,int>
    #define cd complex<double>
    #define ull unsigned long long
    #define base 1000000000000000000
    #define fio ios::sync_with_stdio(false);cin.tie(0)
    
    using namespace std;
    
    const double eps=1e-6;
    const int N=20000+10,maxn=500000+10,inf=0x3f3f3f3f,INF=0x3f3f3f3f3f3f3f3f;
    
    multiset<int>p;
    int a[N];
    int ans[N];
    int main()
    {
        int n;
        scanf("%d",&n);
        for(int i=1,x;i<=n;i++)
        {
            scanf("%d",&x);
            if(x>0)a[x]++;
            else if(x==0)p.insert(i);
            else
            {
                if(a[-x]>0)a[-x]--;
                else if(p.size()!=0)
                {
    //                printf("--%d
    ",*p.begin());
                    ans[*p.begin()]=-x;
                    p.erase(p.begin());
                }
                else return 0*puts("No");
            }
        }
        while(p.size()!=0)ans[*p.begin()]=1,p.erase(p.begin());
        puts("Yes");
        for(int i=1;i<=n;i++)
            if(ans[i]!=0)
                printf("%d ",ans[i]);
        puts("");
        return 0;
    }
    /********************
    
    ********************/
    View Code

    补题****************************************************************************

    F - The Final Level

    题目大意,有若干个L形连通块,两边长为n,有一个重叠, 问你最少用几个能把(0 , 0)和(a, b)连起来, L形的物件不能有交叉。

    思路:分类讨论贪心,分为一下几种情况。

    1.a - x < n && b - y < n   用一个L就能连通

    2.a - x > n && b - y > n   贪心地继续连在前一个的末端

    3.a - x > n && b - y < n   y这维不用贪了,贪x这维。

    4.与3相反。

    #include<bits/stdc++.h>
    #define LL long long
    #define fi first
    #define se second
    #define mk make_pair
    #define pii pair<int, int>
    
    using namespace std;
    
    const int N = 2e5 + 7;
    const int M = 1e5 + 7;
    const int inf = 0x3f3f3f3f;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const int mod = 1e9 +7;
    
        
    int T;
    LL a, b, n;
    bool flag = false;
    vector<pair<pair<LL, LL>, pair<LL, LL> > > ans;
    
    void dfs(LL x, LL y) {
        if(a - x < n && b - y < n) {
            if(!flag) {
                int x1 = x - (x + n - 1 - a);
                int y1 = y;
                int x2 = a;
                int y2 = y + n - 1;
                ans.push_back(mk(mk(x2, y2), mk(x1, y1)));
                return;
            } else {
                int x2 = x;
                int y2 = y - (y + n - 1 - b);
                int x1 = x + n - 1;
                int y1 = b;
                ans.push_back(mk(mk(x2, y2), mk(x1, y1)));
            }
            return;
        }
    
        if(b - y < n) {
            ans.push_back(mk(mk(x + n - 1, y - n + 1), mk(x, y)));
            flag = true;
            dfs(x + n, y);
            return;
        }
    
        if(a - x < n) {
            ans.push_back(mk(mk(x, y), mk(x - n + 1, y + n - 1)));
            flag = false;
            dfs(x, y + n);
            return;
        }
    
    
        if(a - x >= n && b - y >= n) {
            ans.push_back(mk(mk(x + n - 1, y + n - 1), mk(x, y)));
            if(abs(a - x) >= abs(b - y)) flag = true, dfs(x + n, y + n - 1);
            else flag = false, dfs(x + n - 1, y + n);
            return;
        }
    
    }
    
    int main() {
        scanf("%d", &T);
        while(T--) {
            ans.clear();
            scanf("%lld%lld%lld", &a, &b, &n);
            int x = a, y = b;
            if(a < 0) a = -a;
            if(b < 0) b = -b;
    
            dfs(0, 0);
    
            for(int i = 0; i < ans.size(); i++) {
                if(a != x) ans[i].fi.fi = -ans[i].fi.fi, ans[i].se.fi = -ans[i].se.fi;
                if(b != y) ans[i].fi.se = -ans[i].fi.se, ans[i].se.se = -ans[i].se.se;
            }
    
            printf("%d
    ", (int) ans.size());
    
            for(int i = 0; i < ans.size(); i++) {
                printf("%lld %lld %lld %lld
    ", ans[i].fi.fi, ans[i].fi.se, ans[i].se.fi, ans[i].se.se);
            }
        }
        return 0;
    }
    
    
    /*
    1
    4 1 3
    */
    View Code
  • 相关阅读:
    还是解决不了滚动条的缩放问题
    全屏问题的解决
    eclipse自带内存监视及回收插件Hidden Heap Status
    Apache2.2“the requested operation has failed”解决方法
    开源软件推介(三)
    Warning: mysql_connect() [function.mysqlconnect]: [2002] 由于连接方在一段时间后没有正确答复或连接的主机没有反应,连接尝试 (trying to connect via tcp://localhost:3306)
    pdf阅读器新需求
    学Linq to sql(十):分层构架的例子(四)
    告别ASP.NET操作EXCEL的烦恼(总结篇)——放到首页奢侈下
    Linq to sql(十):分层构架的例子(二)
  • 原文地址:https://www.cnblogs.com/CJLHY/p/9291194.html
Copyright © 2020-2023  润新知