多校第五场

5783.Divide the Sequence

题意:给出一段序列,尽可能多得分割序列使得每段前缀和非负。



分析:既然前缀和非负,那么从后往前遍历,若非负则++。


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include <iostream>
#include <algorithm>
#include <string>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <vector>
#include <bitset>
using namespace std;

#define LL long long
#define F(i,a,b) for (int i=(a),_##i=(b); i<=_##i; i++)
#define Rof(i,a,b) for (int i=(a),_##i=(b); i>=_##i; i--)
#define rep(i,a,b) for (int i=(a),_##i=(b); i<=_##i; i++)
#define rek(i,a,b) for (int i=(a),_##i=(b); i>=_##i; i--)
#define mem(a,b) memset(a,b,sizeof(a))
#define Cpy(a,b) memcpy(a,b,sizeof(b))
int a[1001000],n;
long long sum,m;
int main()
{
    //freopen("in.txt","r",stdin);
    while(scanf("%d",&n)==1)
    {
        sum=m=0;
        F(i,1,n) scanf("%d",a+i);
        for(int i=n;i;--i)
        {
            m+=a[i];
            if(m>=0)
            {
                sum++;m=0;
            }
        }
        printf("%I64d\n",sum);
    }
    return 0;
}

5791.Two



题意:给出两个数字序列,求两个序列的公共子序列的个数(可重复)



分析:可dp,可用树状数组做。

先给出dp方程,再解释.

dp[i][j]=(dp[i-1][j]+dp[i][j-1]-dp[i-1][j-1])%mod;——1
if(dp[i][j]<0) dp[i][j]+=mod;——2
if(a[i]==b[j]) dp[i][j]=(dp[i][j]+dp[i-1][j-1]+1)%mod;——3

第一个是每次都要使用的,因为dp[i][j]要加上除去a[i]的(dp[i-1][j]),加上除去b[j]的(dp[i][j-1],再减去重复加的(dp[i-1][j-1],就ok啦。

第二个是保证dp[i][j]为正,因为在减dp[i-1][j-1]中可能为负,故要处理。

最后是第三个,因为如果a[i]==b[j],那么对前面的所有都可加上a[i],b[j],所以要加一遍dp[i-1][j-1],然后a[i]和b[j]单独匹配得到,需要+1,

举个例子:

1 2 3 4

1 2

匹配到2时,前面所有的匹配到的(1,1)都可变成(1 2,1 2)所以需要加一遍dp[i-1][j-1],ok啦。


//jing miao de dong gui
#include<cstdio>
#include<cstring>
const int mod=1000000007;
int dp[1010][1010];
int a[1010],b[1010],n,m;

int main()
{
    while(scanf("%d%d",&n,&m)==2)
    {
        memset(dp,0,sizeof(dp));
        for(int i=1;i<=n;++i) scanf("%d",a+i);
        for(int i=1;i<=m;++i) scanf("%d",b+i);
        for(int i=1;i<=n;++i)for(int j=1;j<=m;++j)
        {
            dp[i][j]=(dp[i-1][j]+dp[i][j-1]-dp[i-1][j-1])%mod;
            if(dp[i][j]<0) dp[i][j]+=mod;
            if(a[i]==b[j]) dp[i][j]=(dp[i][j]+dp[i-1][j-1]+1)%mod;
        }
        printf("%d\n",dp[n][m]);
    }
}

5792.World is Exploding

题意:给出数字序列,找出满足某些条件的四个数的组数,Aa<Ab&&a<b,Ac>Ad&&c<d.



分析:因为数字范围很大(达到1e9),而个数最多只有5万个,故要离散化。然后对每个数统计左边大于(l[])和小于(l1[])它的数,右边大于(r[])和小于(r1[])它的数。

最后处理特殊情况,左边*右边-特殊情况就可以得到结果了,具体见BC的blog。


#include<bits/stdc++.h>
using namespace std;
const int maxn = 5e4+7;
int d[maxn],n,a[maxn],l[maxn],r[maxn],l1[maxn],r1[maxn];
inline int lowbit(int x){
    return x&(-x);
}
//改点求段
inline void update(int x,int v){
    for(int i=x;i<maxn;i+=lowbit(i))
        d[i]+=v;
}
//d[1]~d[x]
inline int get(int x){
    int ans = 0;
    for(int i=x;i;i-=lowbit(i))
        ans+=d[i];
    return ans;
}
map<int,int>H;
vector<int> V;
int main(){
    while(scanf("%d",&n)!=EOF){
        fill(l1,l1+maxn-1,0);
        //memset(l1,0,sizeof(l1));
        memset(r1,0,sizeof(r1));
        memset(l,0,sizeof(l));
        memset(r,0,sizeof(r));
        memset(d,0,sizeof(d));
        V.clear();H.clear();
        for(int i=1;i<=n;i++)
        {
            scanf("%d",a+i);
            V.push_back(a[i]);
        }
        sort(V.begin(),V.end());//排序
        V.erase(unique(V.begin(),V.end()),V.end());//去重+翻转数列
        //for(int i=0;i<n;i++) printf("%d ",V[i]);
        for(int i=0;i<V.size();i++)//hash?
            H[V[i]]=i+1;
        for(int i=1;i<=n;i++)a[i]=H[a[i]];

        long long ans1=0,ans2=0,ans3=0;//树状数组求左边大于或小于它的数
        for(int i=1;i<=n;i++){
            l[i]=get(a[i]-1);
            l1[i]=get(maxn-1)-get(a[i]);
            update(a[i],1);
        }
        memset(d,0,sizeof(d));
        for(int i=n;i>=1;i--){//更新加计算 右边大于或小于它的数
            r[i]=get(a[i]-1);
            r1[i]=get(maxn-1)-get(a[i]);
            update(a[i],1);
        }
        for(int i=1;i<=n;i++) printf("l[i]=%d l1[i]=%d r[i]=%d rl[i]=%d\n",l[i],l1[i],r[i],r1[i]);
        for(int i=1;i<=n;i++){//统计
            ans3+=1ll*l[i]*r[i];
            ans3+=1ll*l1[i]*r1[i];
            ans3+=1ll*l[i]*l1[i];
            ans3+=1ll*r[i]*r1[i];
            ans1+=l[i],ans2+=r[i];
        }
        cout<<ans1*ans2-ans3<<endl;//小的*大的-特殊情况
    }
}
时间: 2024-08-24 14:25:58

多校第五场的相关文章

多校第五场 归并排序

HDU 4911 Inversion 考点:归并排序 思路:这题呀比赛的时候忘了知道可以用归并排序算出逆序数,但是忘了归并排序的实质了,然后不会做-- 因为看到题上说是相邻的两个数才能交换的时候,感觉归并排序好像不是得要相邻的呀,然后就这样晕--刚才重新看了才发现,归并就是相邻的交换的,正好是用来求逆序数的,唉--真的是做这个归并排序比赛就来了--真好! #include<iostream> #include<cstdio> #include<cstring> #inc

2014多校第五场1010 || HDU 4920 Matrix multiplication(矩阵乘法优化)

题目链接 题意 : 给你两个n*n的矩阵,然后两个相乘得出结果是多少. 思路 :一开始因为知道会超时所以没敢用最普通的方法做,所以一直在想要怎么处理,没想到鹏哥告诉我们后台数据是随机跑的,所以极端数据是不可能会有的,而我们一开始一直在想极端数据能接受的方法......后来看了鹏哥的做法,就是把是0的地方都跳过就可以了,用矩阵保存前一个非0数的位置是多少.二师兄给我看了一个代码,人家根本没用别的优化,直接将最里层k的循环提到了最外层,然后就AC了,对此我表示无语. 1 #include <cstd

2014 HDU多校弟五场J题 【矩阵乘积】

题意很简单,就是两个大矩阵相乘,然后求乘积. 用 Strassen算法 的话,当N的规模达到100左右就会StackOverFlow了 况且输入的数据范围可达到800,如果变量还不用全局变量的话连内存开辟都开不出来 1 #pragma comment(linker, "/STACK:16777216") 2 #include <iostream> 3 #include <stdio.h> 4 #define ll long long 5 using namesp

2014多校第五场1001 || HDU 4911 Inversion (归并求逆序数)

题目链接 题意 : 给你一个数列,可以随意交换两相邻元素,交换次数不超过k次,让你找出i < j 且ai > aj的(i,j)的对数最小是多少对. 思路 : 一开始想的很多,各种都想了,后来终于想出来这根本就是求逆序数嘛,可以用归并排序,也可以用树状数组,不过我们用树状数组做错了,也不知道为什么.求出逆序数来再减掉k次,就可以求出最终结果来了.求逆序数链接1,链接2 1 #include <stdio.h> 2 3 int left[250003], right[250003];

2014 HDU多校弟五场A题 【归并排序求逆序对】

这题是2Y,第一次WA贡献给了没有long long 的答案QAQ 题意不难理解,解题方法不难. 先用归并排序求出原串中逆序对的个数然后拿来减去k即可,如果答案小于0,则取0 学习了归并排序求逆序对的方法,可以拿来当模板 TVT 贴代码了: 1 #include <stdio.h> 2 #include <string.h> 3 #include <stdlib.h> 4 #include <math.h> 5 #include <iostream&g

2019 湖南多校第五场题解

解题过程 开场byf去修锅,各种spj没写,还有写挂的.开场shl写A,lfw写K,shl写E,shl写G,前期签到顺利.随后lfw推出D的规律,开始写,遇到了一些错误,首先MLE了,因为k^2预处理,lfw用的string来存不同的子串丢到unordered_map里,那么就是k^3的存储,肯定炸,接着换成了hash值,但是单关键字冲突了,WA了一发,接着用双关键字,使用一个pair存map,map带的logn常数MLE了一发,中间B题加上了spj,lfw习惯性输出空格,WA一发后过了,最后l

hdu 6088 Rikka with Rock-paper-scissors (2017 多校第五场 1004) 【组合数学 + 数论 + 模意义下的FFT】

题目链接 首先利用组合数学知识,枚举两人的总胜场数容易得到 这还不是卷积的形式,直接搞的话复杂度大概是O(n^2)的,肯定会TLE.但似乎和卷积有点像?想半天没想出来..多谢Q巨提醒,才知道可以用下面这个公式进行转化 最后,化得的公式为 另外注意,上式右边是一个卷积的形式,但是,所得和的第一项是不需要加上的(不过图中公式没有体现).结合实际意义大概就是,i==0&&j==0时,gcd(i,j)不存在约数d,虽然0可以被任意正整数整除 & 第一项不为0 #include<bit

[补]2019HDU杭电多校第五场H

红小豆又被奇怪的东西卡住了 参考于:思路https://www.cnblogs.com/st1vdy/p/11309280.html 样例https://www.cnblogs.com/dd-bond/p/11308155.html HDU-6631 line symmetric 多边形轴对称类问题.关于多边形轴对称目前可以公开的情报可见第一篇blog的大佬画的图,主要就是奇偶问题.本题主要思路是枚举实现找轴和验证对称,注意判自交的方式. 初步认识可以做一下hdu3902. 在下还是专注于讲心路

2019 杭电多校 第五场

2019 Multi-University Training Contest 5 补题链接:2019 Multi-University Training Contest 5 罚时爆炸 自闭场 1004 equation (HDU 6627) 题意: 给定一个整数 \(C\) 和 \(N\) 组 \(a_i,b_i\),求 \(∑_{i=1}^N|a_i\cdot x + b_i| = C\) 的所有解,如果有无穷多个解就输出 -1. 思路 分类讨论 分类讨论去绝对值.根据 \(b_i / a_i