• 暑假第二十一测


    题解:

    第一题:

    #include<bits/stdc++.h>
    using namespace std;
    
    
    const int M = 100005, ME = 1000005;
    struct edge{int u, v, w;}G[ME];
    int fa[M], siz[M], tot, val[M];
    int find(int x){
        if(fa[x] == x)return x;
        return fa[x] = find(fa[x]);
    }
    bool cmp(edge a, edge b){
        return a.w > b.w;
    }
    void add(int u, int v, int w){
        G[++tot].u = u; G[tot].v = v; G[tot].w = w;
    }
    int main(){
        freopen("zoo.in","r",stdin);
        freopen("zoo.out","w",stdout);
        int n, m;
        long long ans = 0;
        scanf("%d%d",&n, &m);
        for(int i = 1; i <= n; i++)scanf("%d", &val[i]);
        int u, v;
        for(int i = 1; i <= m; i++){
            scanf("%d%d", &u, &v);
            add(u, v, min(val[u], val[v]));
        }
        sort(G + 1, G + 1 + tot, cmp);
        for(int i = 1; i <= n; i++) fa[i] = i, siz[i] = 1;
        for(int i = 1; i <= m; i++){
            int u = G[i].u, v = G[i].v;
            if(find(u) == find(v))continue;
            else {
                int x = find(u), y = find(v);
                fa[x] = y;
                ans += 1LL*G[i].w * siz[x] * siz[y] * 2;
                siz[y] += siz[x]; 
            }
        }
        printf("%I64d
    ", ans);
        
    }
    View Code

     第二题:解法一:

    以下是std:

    #include<cstdio>
    #include<algorithm>
    #include<map>
    using namespace std;const int N=2*1e5+10;int n;int m;int T;
    map <int,int> mp;
    struct treearray
    {
        int ta[2*N];
        inline void c(int x,const int& t){for(;x<=n;x+=x&(-x))ta[x]+=t;}
        inline int q(int x){int r=0;for(;x>0;x-=x&(-x))r+=ta[x];return r;}
        inline void clear(){for(int i=0;i<=n;i++)ta[i]=0;}
    }ta1,ta2;
    struct op{int tp;int l;int r;}op[N];int nu[N];
    inline void solve(int z)
    {
        scanf("%d",&m);
        for(int i=1;i<=m;i++)scanf("%d%d",&op[i].tp,&op[i].l);
        for(int i=1;i<=m;i++)if(op[i].tp==0){++n,op[i].r=op[i].l+n;nu[n]=i;}
        for(int i=1;i<=m;i++)if(op[i].tp==0)mp[op[i].l]=1,mp[op[i].r]=1;
        map <int,int>:: iterator it1,it;
        for(it=mp.begin(),it1=it,++it1;it1!=mp.end();++it,++it1)it1->second+=it->second;
        for(int i=1;i<=m;i++)if(op[i].tp==0){op[i].l=mp[op[i].l],op[i].r=mp[op[i].r];}
        n=mp.size();
        printf("Case #%d:
    ",z);
        for(int i=1;i<=m;i++)
        {
            if(op[i].tp==0)
            {
                int x1=ta1.q(op[i].r)-ta1.q(op[i].l-1);int x2=ta2.q(op[i].r)-ta2.q(op[i].l-1);
                int x3=ta1.q(op[i].r)-ta2.q(op[i].l-1);printf("%d
    ",x1+x2-x3);
                ta1.c(op[i].l,1);ta2.c(op[i].r,1);
            }
            else 
            {int l=op[nu[op[i].l]].l;int r=op[nu[op[i].l]].r;ta1.c(l,-1);ta2.c(r,-1);}
        }
    }
    inline void clear(){mp.clear();ta1.clear();ta2.clear();n=0;}
    int main()
    {
        freopen("segment.in","r",stdin);
        freopen("segment.out","w",stdout);
        scanf("%d",&T);for(int z=1;z<=T;z++){solve(z);clear();}
        fclose(stdin);fclose(stdout);return 0;
    }
    View Code

     解法二:CDQ分治,一维时间,二维插入位置归并递减,三维结束位置树状数组;

    #include<bits/stdc++.h>
    using namespace std;
    
    
    const int M = 200005;
    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*10+c-'0';c=getchar();}
        return x *= f;
    }
    
    struct Point{int x, y, id, v;}p[M], t[M], now[M];
    int ans[M], cnt, c[M], Lx, dis[M];
    bool no[M];
    inline int lowbit(int x){return x & (-x);}
    void add(int pos, int v){
        for(int x = pos; x <= Lx; x += lowbit(x))
            c[x] += v;
    }
    int query(int pos){
        int ret = 0;
        for(int x = pos; x; x -= lowbit(x))
            ret += c[x];
        return ret;
    }
    
    void cdq(int lf, int rg){
        if(lf == rg)return ;
        int mid = (lf + rg) >> 1;
        cdq(lf, mid); cdq(mid + 1, rg);
        int i = lf, j = mid + 1, num = lf;
        while(i <= mid && j <= rg){
            if(p[i].x >= p[j].x){
                add(p[i].y, p[i].v); now[num++] = p[i++];
            }
            else {
                if(!no[p[j].id]) ans[p[j].id] += query(p[j].y); 
                now[num++] = p[j++];
            }
        }
        while(j <= rg)ans[p[j].id] += query(p[j].y), now[num++] = p[j++];
        for(int e = lf; e < i; e++)add(p[e].y, -p[e].v);
        while(i <= mid)now[num++] = p[i++];
        for(int e = lf; e <= rg; e++)p[e] = now[e];
    }
    void init(){
        memset(no, 0, sizeof(no));
        memset(ans, 0, sizeof(ans));
        cnt = 0;
    }
    
    int main(){
        freopen("segment.in","r",stdin);
        freopen("segment.out","w",stdout);
        int T, tt=0;
        scanf("%d", &T);
        while(T--){
            init();
            int n = read();
            for(int i = 1; i <= n; i++){
                int opt = read(), y = read();
                if(!opt){
                    dis[++cnt] = y + cnt;
                    p[i].x = y, p[i].y = y + cnt, p[i].v = 1, p[i].id = i;
                    t[cnt] = p[i];
                }
                else {
                    p[i] = t[y]; no[i] = 1;
                    p[i].v = -1, p[i].id = i;
                }
            }
            sort(dis + 1, dis + 1 + cnt);
            Lx = unique(dis + 1, dis + 1 + cnt) - dis - 1;
            for(int i = 1; i <= n; i++)
                p[i].y = lower_bound(dis + 1, dis + 1 + Lx, p[i].y) - dis;
            cdq(1, n);
            printf("Case #%d:
    ",++tt);
            for(int i = 1; i <= n; i++)
                if(!no[i])printf("%d
    ", ans[i]);
        }
    }
    View Code

    第三题:题中有一个性质, k < max(n, m) 所以一定有一行或一列为空,那么我们前年的行都可随便填,最后一行使上面满足就可以了,对于一列也只需要用最后一个满足就可以了所以一行就是2^(剩余格子 - 1);

    最后一行满足前面的要求,最后一行也不会矛盾,证明如下:

    1。(m + n) % 2 ==1, 方案数为0,;

    m行每行要奇数个-1, (-1)^m,n列每列要奇数个-1, (-1)^n, (-1)^n != (-1)^m

    2。n, m 为奇数;前偶数行每行奇数个-1,有奇数*偶数个-1 = 偶数个-1,减去 偶数个-1(成对,影响抵消)= 偶数个-1,最后一行就要偶数个1, 那么-1要奇数个, 符合条件;

    n,m为偶数,证法同上; 

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    const int M = 1000005;
    ll mod;
    int n, m, k, len[M], cnt[M];
    ll ksm(ll a, ll b){
        ll ret = 1;
        for( ; b; b >>= 1, a = a * a % mod)
            if(b & 1)ret = ret * a % mod;
        return ret;
    }
    
    
    int main(){
        freopen("number.in","r",stdin);
        freopen("number.out","w",stdout);
        scanf("%d%d%d", &n, &m, &k);
        int x, y, w;
        ll ans = 1;
        if(n >= m){
            for(int i = 1; i <= n; i++)len[i] = m;
            for(int i = 1; i <= k; i++){
                scanf("%d%d%d", &x, &y, &w);
                len[x]--;
                if(w == -1)cnt[x]++;
            }    
        }
        else {
            swap(n, m);
            for(int i = 1; i <= n; i++)len[i] = m;
            for(int i = 1; i <= k; i++){
                scanf("%d%d%d", &x, &y, &w);
                swap(x, y);len[x]--;
                //fprintf(stderr, "%d %d
    ", x, y);
                if(w == -1)cnt[x]++;
            }
        }
        scanf("%I64d", &mod);
        if(n % 2 != m % 2){puts("0");return 0;}
        for(int i = 1; i <= n; i++){
            if(len[i] == m){
                for(int j = 1; j <= n; j++){
                    if(i == j)continue;
                    if(!len[j]){
                        if(cnt[j]%2 == 0){puts("0");return 0;}
                    }
                    else ans = ans * ksm(2, len[j] - 1) % mod;
                }
                break;
            }
        }
        printf("%I64d
    ", ans);
    }
    View Code

    今天终于当了一次战力巅峰,贴一张图

  • 相关阅读:
    leetcode 之 Palindrome Partitioning
    虚拟机共享文件夹下tar
    leetcode 之 Excel Sheet Column Number
    AndroidHttpClient & jsoup 解析 正方教务系统
    查看android下的分区表
    ubuntukylin 下编译 android4.4
    android:layout_weight 和 android: weightSum的使用
    Intent 与Bundle的传值关系
    使用自定义的Toast
    SlideMenu例子解析2
  • 原文地址:https://www.cnblogs.com/EdSheeran/p/9513230.html
Copyright © 2020-2023  润新知