• 2021杭电多校第一场


    【Maximal submatrix】

    题面:给出一个N * M矩阵,求出最大的列上升子矩阵

    1.矩阵处理

    for(int i=1;i<=n;i++)
            {
                for(int j=1;j<=m;j++)
                {
                    if(mp[i][j] >= mp[i-1][j])
                        mp1[i][j] = mp1[i-1][j] + 1;
                    else
                        mp1[i][j] = 1;
                }
            }

     接下来问题转换为 对该矩阵求最大的子矩阵大小

     如上图,我们可以把每一行的数字考虑为一个高为mp1[i][j]的方块,利用单调栈分别求解每一行的最大子矩形面积复杂度为O(N * M)

    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <stack>
    #include <queue>
    #include <map>
    #include <set>
    #include <vector>
    #include <math.h>
    #include <bitset>
    #include <algorithm>
    #include <climits>
    #include<functional>
    #include<time.h>
    #include<stdlib.h>
    #include<sstream>
    #include <iomanip>
    #include<list>
    #include "assert.h"
    using namespace std;
    #define Pair pair<int, int>
    #define ULL unsigned long long
    #define LS l,mid,lson
    #define RS mid+1,r,rson
    #define MEM(a,x) memset(a,x,sizeof(a))
    #define gcd(a,b) __gcd(a,b)
    #define ll long long
    #define esp 1e-8
    #define lowbit(x) (x&-x)
    #define girlfriend zy
    #define E exp(1.0)
    #define PI acos(-1.0)
    //#define int long long
    #define pb(x) push_back(x)
    #define debug(x) cout<<#x<<" "<<x<<endl;
    #define rtf return false;
    #define rtt return true;
    // lower_bound(a.begin(),a.end(),tmp,greater<ll>()) 第一个小于等于的
    void puty(){puts("YES");}
    void putn(){puts("NO");}
    const int maxn = 4e5 + 10;
    const int MOD = 1e9 + 7;
    const int mod = 998244353;
    const int INF = 0x3f3f3f3f; ///1 061 109 567
    const int maxx = 1e7 + 10;
    int mp[2020][2020];
    int mp1[2020][2020];
    int n,m;
    struct node
    {
        int val,cnt;
    };
    node x[2020];
    int getarea(int a[])
    {
        int ans = 0;
        for(int i = 1 ;i <= m;i++)
        {
            x[i].val = a[i];
            x[i].cnt = i;
        }
        stack<node> st;
        x[m+1].val = 0;
        st.push(x[1]);
        for(int i=1;i<=m+1;i++)
        {
            if(x[i].val > st.top().val)
                st.push(x[i]);
            else
            {
                int left = 0;
                while(!st.empty() && x[i].val <= st.top().val)
                {
                    node j;
                    j = st.top();
                    st.pop();
                    ans = max(ans,(i - j.cnt) * j.val);
                    left = j.cnt;
                }
                x[i].cnt = left;
                st.push(x[i]);
            }
        }
        return ans;
    }
    int main()
    {
        int t;
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d%d",&n,&m);
            for(int i=1;i<=n;i++)
            {
                for(int j=1;j<=m;j++)
                {
                    scanf("%d",&mp[i][j]);
                }
            }
            for(int i=1;i<=n;i++)
            {
                for(int j=1;j<=m;j++)
                {
                    if(mp[i][j] >= mp[i-1][j])
                        mp1[i][j] = mp1[i-1][j] + 1;
                    else
                        mp1[i][j] = 1;
                }
            }
            int ans = 0;
            for(int i=1;i<=n;i++)
            {
                ans = max(ans,getarea(mp1[i]));
            }
            printf("%d
    ",ans);
        }
    
    }
    View Code

     

    【Xor sum】

    题面:给出n个数,找到最短的区间异或和大于等于K 若没有则输出" - 1 "

    思路:01字典树处理区间异或最大值,同时更新区间长度和左右端点

    (1)区间异或处理:处理整个数组的前缀异或和(每个前缀和的值与整个字典树查找最大值与K的关系) 操作完成之后再将这个值插入字典树

        ————原理(假设当前枚举到的前缀和在数组中的位置为R  众所周知a[r]  ^ a[l]  =  a[l  —> r -1]的异或和 )

        由X xor X = 0 ; 0 xor Y = Y;所有【l,r】 = 【1,r】 XOR 【1,l - 1】 
        这样在一颗加入了r 前的所有前缀异或和的01字典树上查找【1,r】就能得到以r为右边界的最大异或和

    (2)然后你需要一个Cnt数组 记录 当前这个节点的值 在数组中最靠右边的位置 因为你要区间最小(好好理解)

    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <stack>
    #include <queue>
    #include <map>
    #include <set>
    #include <vector>
    #include <math.h>
    #include <bitset>
    #include <algorithm>
    #include <climits>
    #include<functional>
    #include<time.h>
    #include<stdlib.h>
    #include<sstream>
    #include <iomanip>
    #include<list>
    #include "assert.h"
    using namespace std;
    #define Pair pair<int, int>
    #define ULL unsigned long long
    #define LS l,mid,lson
    #define RS mid+1,r,rson
    #define MEM(a,x) memset(a,x,sizeof(a))
    #define gcd(a,b) __gcd(a,b)
    #define ll long long
    #define esp 1e-8
    #define lowbit(x) (x&-x)
    #define girlfriend zy
    #define E exp(1.0)
    #define PI acos(-1.0)
    //#define int long long
    #define pb(x) push_back(x)
    #define debug(x) cout<<#x<<" "<<x<<endl;
    #define rtf return false;
    #define rtt return true;
    // lower_bound(a.begin(),a.end(),tmp,greater<ll>()) 第一个小于等于的
    void puty(){puts("YES");}
    void putn(){puts("NO");}
    const int maxn = 1e7 + 10;
    const int MOD = 1e9 + 7;
    const int mod = 998244353;
    const int INF = 0x3f3f3f3f; ///1 061 109 567
    int tree[maxn][2];
    int a[maxn];
    int cnt[maxn];
    int tot = 0;
    int k;
    void insert(int x,int pos)
    {
        int s = 0,tmp;
        for(int i=31;i>=0;i--)
        {
            tmp = x >> i & 1;
            if(!tree[s][tmp])
                tree[s][tmp] = ++tot;
            s = tree[s][tmp];
            cnt[s] = max(cnt[s],pos);
        }
    }
    int get(int x)
    {
        int s = 0,tmpk,tmpx;
        int l = 0;
        for(int i=31;i>=0;i--)
        {
            tmpx = x >> i & 1;
            tmpk = k >> i & 1;
            if(!tmpx)
            {
                if(!tmpk)
                {
                    l = max(l,cnt[tree[s][1]]);
                    if(!tree[s][0]) return l;
                       s = tree[s][0];
                }
                else
                {
                    if(!tree[s][1]) return l;
                        s = tree[s][1];
                }
            }
            else
            {
                if(!tmpk)
                {
                    l = max(l,cnt[tree[s][0]]);
                    if(!tree[s][1]) return l;
                        s = tree[s][1];
                }
                else
                {
                    if(!tree[s][0]) return l;
                        s = tree[s][0];
                }
            }
        }
        return l = max(l,cnt[s]);
    }
    int main()
    {
        int t;
        scanf("%d",&t);
        while(t--)
        {
            int n;
            scanf("%d%d",&n,&k);
            for(int i=0;i<=tot;i++)
            {
                tree[i][0] = tree[i][1] = 0;
                cnt[i] = 0;
            }
            tot = 0;
            for(int i=1;i<=n;i++)
            {
                scanf("%d",&a[i]);
                a[i] ^= a[i-1];
            }
            int ans = INF;
            int ansl = 0,ansr = 0;
            insert(0,0);
            for(int i=1;i<=n;i++)
            {
                int l = get(a[i]);
                if(l && i - l < ans)
                {
                    ans = i - l;
                    ansl = l + 1;
                    ansr = i;
                }
                insert(a[i],i);
            }
            if(ans != INF)
            {
                printf("%d %d
    ",ansl,ansr);
            }
            else
            {
                printf("-1
    ");
            }
        }
    }
    View Code

    【KD-Graph】

    思路:按边从小到大排序,维护连通块数量 等于K时 答案 = e[i-1].val 然后跟 e[i].val比较 如果相等 输出 “-1" 不相等输出e[i-1].val

    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <stack>
    #include <queue>
    #include <map>
    #include <set>
    #include <vector>
    #include <math.h>
    #include <bitset>
    #include <algorithm>
    #include <climits>
    #include<functional>
    #include<time.h>
    #include<stdlib.h>
    #include<sstream>
    #include <iomanip>
    #include<list>
    #include "assert.h"
    using namespace std;
    #define Pair pair<int, int>
    #define ULL unsigned long long
    #define LS l,mid,lson
    #define RS mid+1,r,rson
    #define MEM(a,x) memset(a,x,sizeof(a))
    #define gcd(a,b) __gcd(a,b)
    #define ll long long
    #define esp 1e-8
    #define lowbit(x) (x&-x)
    #define girlfriend zy
    #define E exp(1.0)
    #define PI acos(-1.0)
    //#define int long long
    #define pb(x) push_back(x)
    #define debug(x) cout<<#x<<" "<<x<<endl;
    #define rtf return false;
    #define rtt return true;
    // lower_bound(a.begin(),a.end(),tmp,greater<ll>()) 第一个小于等于的
    void puty(){puts("YES");}
    void putn(){puts("NO");}
    const int maxn = 1e7 + 10;
    const int MOD = 1e9 + 7;
    const int mod = 998244353;
    const int INF = 0x3f3f3f3f; ///1 061 109 567
    struct node
    {
        int from,to,val;
        node(int u,int v,int w)
        {
            from = u,to = v,val = w;
        }
        node(){};
    }e[maxn];
    int head[maxn];
    int pre[maxn];
    int find(int x)
    {
        if(x == pre[x])
            return x;
        return pre[x] = find(pre[x]);
    }
    void uoin(int x,int y)
    {
        int fx = find(x);
        int fy = find(y);
        if(fx == fy)
            return;
        pre[fx] = fy;
    }
    int cmp(node a,node b)
    {
        return a.val < b.val;
    }
    int main()
    {
    //    freopen("1.in","r",stdin);
        //freopen("1.out","w",stdout);
        int t;
        scanf("%d",&t);
        while(t--)
        {
            int n,m,k;
            scanf("%d%d%d",&n,&m,&k);
            for(int i=1;i<=n;i++)
            {
                head[i] = -1;
                pre[i] = i;
            }
            for(int i=1;i<=m;i++)
            {
                int u,v,w;
                scanf("%d%d%d",&u,&v,&w);
                e[i] = {node{u,v,w}};
            }
            sort(e+1,e+1+m,cmp);
            int ans = 0;
            int comp = 0;
            int tot = n;
            for(int i=1;i<=m;i++)
            {
                int fx = find(e[i].from);
                int fy = find(e[i].to);
                if(tot == k)
                {
                    ans = e[i-1].val;
                    comp = e[i].val;
                }
                if(fx != fy)
                {
                    uoin(fx,fy);
                    tot--;
                }
            }
            if(comp == ans)
            {
                printf("-1
    ");
            }
            else
            {
                printf("%d
    ",ans);
            }
        }
    }
    View Code

    【zoto】

    思路:莫队按x轴分块维护每一个块的区间,然后用树状数组维护(线段树T了 Orz)对跟Y轴平行方向上的点的个数 

    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <stack>
    #include <queue>
    #include <map>
    #include <set>
    #include <vector>
    #include <math.h>
    #include <bitset>
    #include <algorithm>
    #include <climits>
    #include<functional>
    #include<time.h>
    #include<stdlib.h>
    using namespace std;
    #define Pair pair<int, int>
    #define ULL unsigned long long
    #define LS l,mid,lson
    #define RS mid+1,r,rson
    #define MEM(a,x) memset(a,x,sizeof(a))
    #define gcd(a,b) __gcd(a,b)
    #define ll long long
    #define N 10
    #define EXP 1e-8
    #define lowbit(x) (x&-x)
    #define girlfriend zy
    #define E exp(1.0)
    #define PI acos(-1.0)
    //#define int long long
    #define pb(x) push_back(x)
    #define debug(x) cout<<#x<<" "<<x<<endl;
    void puty(){puts("YES");}
    void putn(){puts("NO");}
    const int maxn = 1e6 + 10;
    const int mod = 1e9 + 7;
    const int INF = 0x3f3f3f3f;
    int fx[100010],b[100010];
    int vis[100010],ans[100010],fen[100010];
    void modify(int x,int k) {
        for(int i=x; i<100010; i+=lowbit(i)) b[i]+=k;
    }
    
    int get(int x) {
        int ans = 0;
        for(int i=x; i; i-=lowbit(i)){
            ans+=b[i];
        }
        return ans;
    }
    
    int query(int x,int y) {
        return get(y)-get(x-1);
    }
    
    struct sut{
        int id,lx,ly,rx,ry;
    }a[100010];
    bool cmp(sut m,sut n){
        return fen[m.lx]==fen[n.lx]?m.rx<n.rx:fen[m.lx]<fen[n.lx];
    }
    void add(int x){
        if(!vis[fx[x]]){
            modify(fx[x],1);
        }
        vis[fx[x]]++;
    }
    void delet(int x){
        if(vis[fx[x]]==1){
            modify(fx[x],-1);
        }
        vis[fx[x]]--;
    }
    
    int main(){
        ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
        int t;
        cin>>t;
        while(t--)
        {
            memset(vis,0,sizeof vis);
            memset(b,0,sizeof(b));
            int n,m;
            cin>>n>>m;
            for(int i=1;i<=n;i++){
                cin>>fx[i];
                fx[i]++;
                fen[i]=(i -1 )/ sqrt(n) + 1;
            }
            for(int i=1;i<=m;i++){
                int lx,ly,rx,ry;
                cin>>lx>>ly>>rx>>ry;
                ly++;
                ry++;
                a[i]={i,lx,ly,rx,ry};
            }
            sort(a+1,a+1+m,cmp);
            int xl=1,xr=0;
            for(int i=1;i<=m;i++){
                while(a[i].lx<xl){
                    add(--xl);
                }
                while(a[i].rx>xr){
                    add(++xr);
                }
                while(a[i].lx>xl){
                    delet(xl++);
                }
                while(a[i].rx<xr){
                    delet(xr--);
                }
                ans[a[i].id]=query(a[i].ly,a[i].ry);
            }
            for(int i=1;i<=m;i++){
                cout<<ans[i]<<endl;
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    netCore3.1项目搭建过程记录-省的每次都傻乎乎的不知道应该先干啥
    探究 position-sticky 失效问题
    协议的设计一般采用结构体进行数据打包,在协议设计的结构体中能不能使用指针 ?
    ROS pluginlib
    ROS NodeHandle命令空间问题
    ROS 常见命令
    ROS ros::spin() 和 ros::spineOnce区别
    PPM图像文件格式
    Qtcreator for visual studio版本调试问题
    Install Typora For Linux
  • 原文地址:https://www.cnblogs.com/lightWh1te/p/15037942.html
Copyright © 2020-2023  润新知