zoukankan      html  css  js  c++  java
  • 2017-2018 ACM-ICPC Northern Eurasia (Northeastern European Regional) Contest (NEERC 17)

    2017-2018 ACM-ICPC Northern Eurasia (Northeastern European Regional) Contest (NEERC 17)

    A.Archery Tournament

    假设当前询问为(x,y),那么能包含它的圆必然是其左边第一个直径(ge y)的或者其右边第一个直径(ge y)的,可以离线下来用线段树来找这两个圆,再判断一下点在不在圆内,先离散化所有点的横坐标,每个圆再线段树中的位置就以其离散化之后的(x)为基准

    //#pragma GCC optimize("O3")
    //#pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<bits/stdc++.h>
    using namespace std;
    function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
    using LL = int_fast64_t;
    const int MAXN = 2e5+7;
    int n;
    vector<int> vec;
    struct SegmentTree{
        int maxx[MAXN<<2], l[MAXN<<2], r[MAXN<<2], ID[MAXN<<2];
        #define ls(rt) rt << 1
        #define rs(rt) rt << 1 | 1
        void pushup(int rt){ maxx[rt] = max(maxx[ls(rt)], maxx[rs(rt)]); }
        void build(int L, int R, int rt){
            l[rt] = L, r[rt] = R;
            maxx[rt] = ID[rt] = 0;
            if(L + 1 == R) return;
            int mid = (L + R) >> 1;
            build(L,mid,ls(rt)); build(mid,R,rs(rt));
        }
        void update(int pos, int rt, int id, int y){
            if(l[rt] + 1 == r[rt]){
                maxx[rt] = y;
                ID[rt] = id;
                return;
            }
            int mid = (l[rt] + r[rt]) >> 1;
            if(pos<mid) update(pos,ls(rt),id,y);
            else update(pos,rs(rt),id,y);
            pushup(rt);
        }
        int QL(int x, int y, int rt){
            if(l[rt]>x or maxx[rt]<y) return -1;
            if(l[rt]+1==r[rt]) return ID[rt];
            int ret = QL(x,y,rs(rt));
            if(ret!=-1) return ret;
            else return QL(x,y,ls(rt));
        }
        int QR(int x, int y, int rt){
            if(r[rt]<=x or maxx[rt]<y) return -1;
            if(l[rt]+1==r[rt]) return ID[rt];
            int ret = QR(x,y,ls(rt));
            if(ret!=-1) return ret;
            else return QR(x,y,rs(rt));
        }
    }ST;
    pair<int,pair<int,int>> Q[MAXN];
    bool shoot(const pair<int,int> &sp, int p){
        pair<int,int> O = Q[p].second;
        if(1ll*O.second*O.second > (O.first-sp.first) * 1ll * (O.first-sp.first) + (O.second-sp.second) * 1ll *(O.second-sp.second)){
            ST.update(lower_bound(vec.begin(),vec.end(),Q[p].second.first)-vec.begin()+1,1,0,0);
            return true;
        }
        return false;
    }
    int main(){
        ____();
        cin >> n;
        ST.build(1,n+1,1);
        for(int i = 1; i <= n; i++){
            cin >> Q[i].first >> Q[i].second.first >> Q[i].second.second;
            vec.emplace_back(Q[i].second.first);
        }
        sort(vec.begin(),vec.end());
        vec.erase(unique(vec.begin(),vec.end()),vec.end());
        for(int i = 1; i <= n; i++){
            if(Q[i].first==1) ST.update(lower_bound(vec.begin(),vec.end(),Q[i].second.first)-vec.begin()+1,1,i,Q[i].second.second<<1);
            else{
                int nx = lower_bound(vec.begin(),vec.end(),Q[i].second.first) - vec.begin() + 1;
                int p = ST.QL(nx,Q[i].second.second,1);
                bool ok = false;
                if(p!=-1) ok = shoot(Q[i].second,p);
                if(!ok){
                    p = ST.QR(nx,Q[i].second.second,1);
                    if(p!=-1) ok = shoot(Q[i].second,p);
                }
                if(ok) cout << p << endl;
                else cout << -1 << endl;
            }
        }
        return 0;
    }
    

    B.Box

    枚举判断即可

    //#pragma GCC optimize("O3")
    //#pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<bits/stdc++.h>
    using namespace std;
    function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
    int a,b,c,w,h;
    bool check(int n, int m){
        if((a+b)*2<=n and (c+2*a<=m or c+2*b<=m)) return true;
        if((a+c)*2<=n and (b+2*a<=m or b+2*c<=m)) return true;
        if((b+c)*2<=n and (a+2*b<=m or a+2*c<=m)) return true;
        if(3*a+b+c<=n and b+c <= m) return true;
        if(3*b+a+c<=n and a+c <= m) return true;
        if(3*c+a+b<=n and a+b <= m) return true;
        return false;
    }
    int main(){
        ____();
        cin >> a >> b >> c >> w >> h;
        if(check(w,h) or check(h,w)) cout << "Yes" << endl;
        else cout << "No" << endl;
        return 0;
    }
    

    C.Connections

    给出一张强连通图,要求保留(2n)条边,剩下的图仍然强连通
    (1)点跑一遍图,然后边取反,再对(1)点跑一遍图,经过的边即为剩下的,且最多有(2n-2)条,补到(2n)条即可
    跑完之后选的边使得(1)号点可以到达任何点,同时任何点可以到达(1)号点,所以保证强连通

    //#pragma GCC optimize("O3")
    //#pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<bits/stdc++.h>
    using namespace std;
    function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
    const int MAXN = 1e5+7;
    vector<pair<int,int> > G[MAXN], rG[MAXN];
    int n,m;
    pair<int,int> edge[MAXN];
    bool vis[MAXN],used[MAXN];
    void dfs(int u, bool rev){
        vis[u] = true;
        for(auto e : (rev?rG[u]:G[u])){
            if(!vis[e.first]){
                used[e.second] = true;
                dfs(e.first,rev);
            }
        }
    }
    void solve(){
        cin >> n >> m;
        for(int i = 1; i <= n; i++){
            G[i].clear();
            rG[i].clear();
        }
        for(int i = 1; i <= m; i++){
            cin >> edge[i].first >> edge[i].second;
            int u = edge[i].first, v = edge[i].second;
            G[u].emplace_back(make_pair(v,i));
            rG[v].emplace_back(make_pair(u,i));
            used[i] = false;
        }
        for(int i = 1; i <= n; i++) vis[i] = false;
        dfs(1,false);
        for(int i = 1; i <= n; i++) vis[i] = false;
        dfs(1,true);
        int cnt = 0;
        for(int i = 1; i <= m; i++){
            if(!used[i]){
                cnt++;
                cout << edge[i].first  << ' ' << edge[i].second << endl;
            }
            if(cnt==m-2*n) break;
        }
    }
    int main(){
        ____();
        int T;
        for(cin >> T; T; T--) solve();
        return 0;
    }
    

    D.Designing the Toy

    给定三视图的面积,要求构造出一个立体图形满足条件,允许方块不叠在一起。
    可以发现如果小的两个的乘积比大的还小是必然构造不了的,否则必然能够构造出一个某一个维度宽度为1的立体图形。
    具体构造看代码,注意坐标的转换

    //#pragma GCC optimize("O3")
    //#pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<bits/stdc++.h>
    using namespace std;
    function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
    const int MAXN = 111;
    int a[3],b[3],match[3];
    bool done[MAXN][MAXN];
    int main(){
        cin >> a[0] >> a[1] >> a[2];
        b[0] = a[0]; b[1] = a[1]; b[2] = a[2];
        sort(b,b+3);
        if(b[0]*b[1]<b[2]){
            cout << -1 << endl;
            return 0;
        }
        cout << b[2] << endl;
        for(int i = 1; i <= b[0]; i++) done[i][i] = true;
        for(int i = b[0] + 1; i <= b[1]; i++) done[1][i] = true;
        int delta = b[2] - b[1];
        for(int i = 1; i <= b[0]; i++) for(int j = 1; j <= b[1]; j++){
            if(!delta) break;
            if(done[i][j]) continue;
            delta--; done[i][j] = true;
        }
        for(int i = 0; i < 3; i++) for(int j = 0; j < 3; j++){
            if(a[i]==b[j]){
                b[j] = -1, match[i] = j;
                break;
            }
        }
        for(int i = 0; i < MAXN; i++) for(int j = 0; j < MAXN; j++){
            if(!done[i][j]) continue;
            if(match[0]==2){
                if(match[1]==0) cout << i << ' ' << j << ' ' << 1 << endl;
                else cout << j << ' ' << i << ' ' << 1 << endl;
            }
            else if(match[1]==2){
                if(match[0]==0) cout << i << ' ' << 1 << ' ' << j << endl;
                else cout << j << ' ' << 1 << ' ' << i << endl;
            }
            else{
                if(match[0]==0) cout << 1 << ' ' << i << ' ' << j << endl;
                else cout << 1 << ' ' << j << ' ' << i << endl;
            }
        }
        return 0;
    }
    

    E.Easy Quest

    简单签到

    //#pragma GCC optimize("O3")
    //#pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<bits/stdc++.h>
    using namespace std;
    function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
    const int MAXN = 1111;
    int n,A[MAXN];
    vector<int> vec;
    int main(){
        ____();
        cin >> n;
        for(int i = 1; i <= n; i++){
            int x; cin >> x;
            if(x>=0) A[x]++;
            else{
                if(A[-x]) A[-x]--;
                else{
                    if(A[0]) A[0]--, vec.emplace_back(-x);
                    else{
                        cout << "No" << endl;
                        return 0;
                    }
                }
            }
        }
        while(A[0]) A[0]--, vec.emplace_back(1);
        cout << "Yes" << endl;
        for(int x : vec) cout << x << ' '; cout << endl;
        return 0;
    }
    

    F.The Final Level

    分四种情况枚举判断一下,要记录一下上一次放的最后一个位置和当前位置的相对位置,先把坐标转换成正的,最后在转换回去

    //#pragma GCC optimize("O3")
    //#pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<bits/stdc++.h>
    using namespace std;
    function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
    int a,b,n,fa,fb;
    vector<pair<pair<int,int>,pair<int,int>>> ret;
    ostream& operator << (ostream &os, const pair<pair<int,int>,pair<int,int>> pr){
        os << pr.first.first*fa << ' ' << pr.first.second*fb << ' ' << pr.second.first*fa << ' ' << pr.second.second*fb;
        return os;
    }
    void dfs(int ca, int cb, int vert){
        int dx = a - ca, dy = b - cb;
        if(dx<n and dy < n){
            if(vert) ret.emplace_back(make_pair(make_pair(ca+dx,cb+n-1),make_pair(ca-(n-1-dx),cb)));
            else ret.emplace_back(make_pair(make_pair(ca,cb-(n-1-dy)),make_pair(ca+n-1,cb+dy)));
            return;
        }
        else if(dx<n){        
            ret.emplace_back(make_pair(make_pair(ca,cb),make_pair(ca+n-1,cb+n-1)));
            dfs(a,cb+n,1);
        }
        else if(dy<n){
            ret.emplace_back(make_pair(make_pair(ca+n-1,cb+n-1),make_pair(ca,cb)));
            dfs(ca+n,b,0);
        }
        else{
            ret.emplace_back(make_pair(make_pair(ca,cb),make_pair(ca+n-1,cb+n-1)));
            if(dx<dy) dfs(ca+n-1,cb+n,1);
            else dfs(ca+n,cb+n-1,0);
        }
    }
    void solve(){
        cin >> a >> b >> n;
        a = a * (fa = a < 0 ? -1 : 1);
        b = b * (fb = b < 0 ? -1 : 1);
        ret.clear();
        dfs(0,0,1);
        cout << ret.size() << endl;
        for(auto p : ret) cout << p << endl;
    }
    int main(){
        ____();
        int T; for(cin >> T; T; T--) solve();    
        return 0;
    }
    

    G.The Great Wall

    H.Hack

    I.Interactive Sort

    J.Journey from Petersburg to Moscow

    给出一张图,求(1)(n)的最短路,其中如果经过的路径超过(k)条,只选择前(k)条的花费
    枚举第(k+1)条边的长度(x),建图时边的长度变成(max(0,w-x)),最后答案为(dist[n]+kcdot x),找最小值即可

    //#pragma GCC optimize("O3")
    //#pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<bits/stdc++.h>
    using namespace std;
    function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
    using LL = int_fast64_t;
    const int MAXN = 3333;
    int n,m,k;
    vector<pair<int,int>> G[MAXN];
    LL dist[MAXN];
    LL Dijkstra(int x){
        memset(dist,0x3f,sizeof(dist));
        dist[1] = 0;
        priority_queue<pair<LL,int>,vector<pair<LL,int>>,greater<pair<LL,int>>> que;
        que.push(make_pair(dist[1],1));
        while(!que.empty()){
            auto p = que.top();
            que.pop();
            int u = p.second;
            LL d = p.first;
            if(dist[u]!=d) continue;
            for(auto e : G[u]){
                int v = e.first, w = max(e.second-x,0);
                if(dist[u]+w<dist[v]){
                    dist[v] = dist[u] + w;
                    que.push(make_pair(dist[v],v));
                }
            }
        }
        return dist[n] + 1ll * k * x;
    }
    int main(){
        scanf("%d %d %d",&n,&m,&k);
        vector<int> vec;
        for(int i = 1; i <= m; i++){
            int u, v, w;
            scanf("%d %d %d",&u,&v,&w);
            G[u].emplace_back(make_pair(v,w));
            G[v].emplace_back(make_pair(u,w));
            vec.emplace_back(w);
        }
        vec.emplace_back(0);
        sort(vec.begin(),vec.end());
        vec.erase(unique(vec.begin(),vec.end()),vec.end());
        LL ret = INT64_MAX;
        for(int x : vec) ret = min(ret,Dijkstra(x));
        printf("%I64d
    ",ret);
        return 0;
    }
    

    K.Knapsack Cryptosystem

    L.Laminar Family

    给定一棵树和其中的一些链,问是否任何两条链只存在包含或者交集为(0)的情况
    树链剖分,以(lca)深度为第一关键字,链长为第二关键字排序所有的链,这样能保证之后的链不可能包含之前的链,只要考虑之后的链是否和之前的链相交即可
    然后找链上最小值和最大值,判断是否相等
    每次找完之后链上各点权值+1

    //#pragma GCC optimize("O3")
    //#pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<bits/stdc++.h>
    using namespace std;
    function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
    const int MAXN = 1e5+7;
    const int INF = 0x3f3f3f3f;
    vector<int> G[MAXN];
    int n,m,dfn[MAXN],rdfn[MAXN],depth[MAXN],son[MAXN],top[MAXN],sz[MAXN],par[MAXN][20],idx;
    struct SegmentTree{
        int minn[MAXN<<2],maxx[MAXN<<2],l[MAXN<<2],r[MAXN<<2],lazy[MAXN<<2];
        #define ls(rt) rt << 1
        #define rs(rt) rt << 1 | 1
        void pushup(int rt){
            minn[rt] = min(minn[ls(rt)],minn[rs(rt)]);
            maxx[rt] = max(maxx[ls(rt)],maxx[rs(rt)]);
        }
        void build(int L, int R, int rt = 1){
            l[rt] = L; r[rt] = R;
            if(L+1==R) return;
            int mid = (L+R) >> 1;
            build(L,mid,ls(rt)); build(mid,R,rs(rt));
        }
        void pushdown(int rt){
            if(!lazy[rt]) return;
            lazy[ls(rt)] += lazy[rt]; lazy[rs(rt)] += lazy[rt];
            minn[ls(rt)] += lazy[rt]; minn[rs(rt)] += lazy[rt];
            maxx[ls(rt)] += lazy[rt]; maxx[rs(rt)] += lazy[rt];
            lazy[rt] = 0;
        }
        int QMIN(int L, int R, int rt = 1){
            if(l[rt]>=R or L>=r[rt]) return INF;
            if(L<=l[rt] and r[rt]<=R) return minn[rt];
            pushdown(rt);
            return min(QMIN(L,R,ls(rt)),QMIN(L,R,rs(rt)));
        }
        int QMAX(int L, int R, int rt = 1){
            if(l[rt]>=R or L>=r[rt]) return 0;
            if(L<=l[rt] and r[rt]<=R) return maxx[rt];
            pushdown(rt);
            return max(QMAX(L,R,ls(rt)),QMAX(L,R,rs(rt)));
        }
        void update(int L, int R, int rt = 1){
            if(l[rt]>=R or L>=r[rt]) return;
            if(L<=l[rt] and r[rt]<=R){
                lazy[rt]++; maxx[rt]++; minn[rt]++;
                return;
            }
            pushdown(rt);
            update(L,R,ls(rt)); update(L,R,rs(rt));
            pushup(rt);
        }
    }ST;
    void modify(int u, int v){
        while(top[u]!=top[v]){
            if(depth[top[u]]<depth[top[v]]) swap(u,v);
            ST.update(dfn[top[u]],dfn[u]+1);
            u = par[top[u]][0];
        }
        if(depth[u]<depth[v]) swap(u,v);
        ST.update(dfn[v],dfn[u]+1);
    }
    int qmin(int u, int v){
        int minn = INF;
        while(top[u]!=top[v]){
            if(depth[top[u]]<depth[top[v]]) swap(u,v);
            minn = min(minn,ST.QMIN(dfn[top[u]],dfn[u]+1));
            u = par[top[u]][0];
        }
        if(depth[u]<depth[v]) swap(u,v);
        return min(minn,ST.QMIN(dfn[v],dfn[u]+1));
    }
    int qmax(int u, int v){
        int maxx = 0;
        while(top[u]!=top[v]){
            if(depth[top[u]]<depth[top[v]]) swap(u,v);
            maxx = max(maxx,ST.QMAX(dfn[top[u]],dfn[u]+1));
            u = par[top[u]][0];
        }
        if(depth[u]<depth[v]) swap(u,v);
        return max(maxx,ST.QMAX(dfn[v],dfn[u]+1));
    }
    bool check(int u, int v){ return qmax(u,v)==qmin(u,v); }
    void dfs1(int u, int f){
        sz[u] = 1; depth[u] = depth[par[u][0] = f] + 1;
        for(int i = 1; par[u][i-1]; i++) par[u][i] = par[par[u][i-1]][i-1];
        for(int v : G[u]){
            if(v==f) continue;
            dfs1(v,u); sz[u] += sz[v];
            if(sz[v]>sz[son[u]]) son[u] = v;
        }
    }
    void dfs2(int u, int tp){
        dfn[u] = ++idx; rdfn[idx] = u;
        top[u] = tp;
        if(son[u]) dfs2(son[u],tp);
        for(int v : G[u]){
            if(v==par[u][0] or v==son[u]) continue;
            dfs2(v,v);
        }
    }
    int LCA(int u, int v){
        if(depth[u]<depth[v]) swap(u,v);
        for(int i = 0; i < 20; i++) if((depth[u]-depth[v])&(1<<i)) u = par[u][i];
        if(u==v) return u;
        for(int i = 19; i >= 0; i--) if(par[u][i]!=par[v][i]){
            u = par[u][i];
            v = par[v][i];
        }
        return par[u][0];
    }
    int main(){
        ____();
        cin >> n >> m;
        for(int i = 1; i < n; i++){
            int u, v; cin >> u >> v;
            G[u].emplace_back(v);
            G[v].emplace_back(u);
        }
        dfs1(1,0); dfs2(1,1);
        vector<pair<pair<int,int>,pair<int,int>>> vec(m);
        for(int i = 0; i < m; i++){
            cin >> vec[i].second.first >> vec[i].second.second;
            int lca = LCA(vec[i].second.first,vec[i].second.second);
            vec[i].first.first = lca;
            vec[i].first.second = depth[vec[i].second.first] + depth[vec[i].second.second] - 2 * depth[lca];
        }
        sort(vec.begin(),vec.end(),[](const pair<pair<int,int>,pair<int,int>> &lhs, const pair<pair<int,int>,pair<int,int>> &rhs){
            if(depth[lhs.first.first]==depth[rhs.first.first]) return lhs.first.second > rhs.first.second;
            else return depth[lhs.first.first] < depth[rhs.first.first];
        });
        ST.build(1,MAXN);
        for(auto pr : vec){
            if(!check(pr.second.first,pr.second.second)){
                cout << "No" << endl;
                return 0;
            }
            modify(pr.second.first,pr.second.second);
        }
        cout << "Yes" << endl;
        return 0;
    }
    
  • 相关阅读:
    Microsoft SQL Server 自定义函数整理大全 [转]
    eclipse将android项目生成apk并且给apk签名
    Android实现对图片的缩放、剪切、旋转、存储
    Android 之 ProgressDialog用法介绍
    Android中Path类的lineTo方法和quadTo方法画线的区别
    Android仿微信二维码扫描
    Android中Bitmap,byte[],Drawable相互转化
    hibernate基础之无法自动创建表总结
    Android获取短信验证码
    Android之常见问题集锦Ⅰ
  • 原文地址:https://www.cnblogs.com/kikokiko/p/12670798.html
Copyright © 2011-2022 走看看