AcWing打卡day6

1.最大的和
思路:利用前缀和把二维数组的一行看成一个整体,然后数组就降到了一维,利用一位数组求连续区间最大值,求就可以了
代码

#include<bits/stdc++.h>
using namespace std;
int pre[110][110];
int a[110][110];
int main()
{
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            cin>>a[i][j];
        }
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            pre[i][j]=pre[i][j-1]+a[i][j];
        }
    }
    int ans=-999999999;
    for(int i=1;i<=n;i++)
    {
        for(int j=i;j<=n;j++)
        {
            int l=0;
            for(int k=1;k<=n;k++)
            {
                if(l<0)
                {
                    l=pre[k][j]-pre[k][i-1];
                }
                else
                {
                    l+=pre[k][j]-pre[k][i-1];
                }
                ans=max(ans,l);
            }
        }
    }
    cout<<ans<<endl;
}

2.动态中位数
思路:利用大根堆和下根堆模拟中位数左右的边的数的情况,如果大根堆为空或数字大于大根堆顶,插入大根堆,否则插入小根堆,如果大根堆的数字个数大于小根堆+1,要匀一个个小根堆,如果小根堆的数字个数大于大根堆,要匀一个个大根堆,(插入奇数个时,大根堆比小根堆多一个,偶数个时,两边数量一样)
代码

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        priority_queue<int> left;
        priority_queue<int,vector<int>,greater<int>> right;
        int id,num;
        scanf("%d%d",&id,&num);
        printf("%d %d\n",id,(num+1)>>1);
        int cnt=0;
        for(int i=1; i<=num; i++)
        {
            int x;
            scanf("%d",&x);
            if(left.empty()||x<=left.top())
            {
                left.push(x);
            }
            else
            {
                right.push(x);
            }
            if(left.size()>=right.size()+2)
            {
                right.push(left.top()),left.pop();
            }
            if(right.size()>left.size())
            {
                left.push(right.top()),right.pop();
            }
            if(i%2)
            {
                printf("%d ",left.top());
                cnt++;
                if(cnt%10==0)
                {
                    printf("\n");
                }
            }
        }
        if(cnt%10)
        printf("\n");
    }
}

3.超快速排序
思路:求逆序对模板题,利用树状数组求就行了,离散化的时候要注意离散的数字里面有0
代码

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
int n;
struct k
{
    long long int data;
    int wz;
}a[600000];
long long int b[600000]={0};
long long int tree[600005]={0};
int low(int x)
{
    return x&-x;
}
bool cmp(struct k x1,struct k x2)
{
    return x1.data<x2.data;
}
void add(int x)
{
    while(x<=n)
    {
        tree[x]++;
        x+=low(x);
    }
}
long long int getsum(int x)
{
    long long int ans=0;
    while(x!=0)
    {
        ans+=tree[x];
        x-=low(x);
    }
    return ans;
}
int main()
{
    
    while(scanf("%d",&n)!=EOF){
    if(n==0)break;
    memset(tree,0,sizeof(tree));
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&a[i].data);
        a[i].wz=i;
    }
    sort(a+1,a+n+1,cmp);
    int cnt=0;
    for(int i=1;i<=n;i++)
    {
        if(a[i].data!=a[i-1].data)
        {
            cnt++;
        }
        b[a[i].wz]=cnt;
    }
    long long int ans=0;
    for(int i=1;i<=n;i++)
    {
        add(b[i]);
        ans+=i-getsum(b[i]);//减去前面比他小的
    }
    printf("%lld",ans);
    }
}

4.奇数码问题
思路:看了一下n的范围,搜索是不可能的,看了一眼标签和逆序对有关,如果把二维地图,一维展开成一行,左右移动不影响逆序对的数量,上下移动,相当于一个数字前进或后退n-1个位置,根据奇偶性原理,如果移动的影响是偶数的话奇偶性不变,那么问题转变成初始态和结束态的逆序对数量的差的奇偶性问题了,如果为偶输出TAK(可以转变),否则输出NIE(不可以转变)
代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll tree[250010];
ll a[250010],b[250010];
ll n;
ll low(ll x)
{
    return x&-x;
}
void add(ll x)
{
    while(x<=n*n-1)
    {
        tree[x]++;
        x+=low(x);
    }
}
ll getSum(ll x)
{
    ll ans=0;
    while(x)
    {
        ans+=tree[x];
        x-=low(x);
    }
    return ans;
}
ll nx(ll sum[250010])
{
    memset(tree,0,sizeof(tree));
    ll ans=0;
    for(int i=1; i<=n*n-1; i++)
    {
        add(sum[i]);
        ans+=i-getSum(sum[i]);
    }
    return ans;
}
int main()
{
    while(cin>>n)
    {
        ll cnt=1;
        for(int i=1; i<=n*n; i++)
        {
            ll x;
            cin>>x;
            if(x==0)
            {
                continue;
            }
            a[cnt++]=x;
        }
        cnt=1;
        for(int i=1; i<=n*n; i++)
        {
            ll x;
            cin>>x;
            if(x==0)
            {
                continue;
            }
            b[cnt++]=x;
        }
        if(abs(nx(a)-nx(b))%2==0)
        {
            cout<<"TAK"<<endl;
        }
        else
        {
            cout<<"NIE"<<endl;
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值