CF Round #632

CF Round #632

再次拉垮

A.构造

题意:给定n*m的棋盘

你对它染色黑或白

对于黑色B的而言,只要它存在白色相邻的格子,它就是满足条件的B'

对于白色的而言,只要它存在黑色相邻的格子,它就是满足条件的W'

构造一种染色方案,使得B'==W'+1,保证存在构造方案

思路:分情况

奇数直接B多W少,交替染色

偶数在交替染色的基础上,找到四个角中的一个,若他是W,把它改成B即可,这样这个B就一定不是B'(相邻一定的无W)

B.数学

给定一个a序列只有1,0,或-1组成,

你有以下的操作

给定b序列,问你可否经过上面的变换将a转化成b

思路:

只要是出现了1和-1,那么啥都可以表示

就是特判有点多,要细心举例,我wa了好几次(吃相难看)

例如

刚刷1,-1,满足否?

-1 1

-2 1

0的判断

-1 1

-1 0

C.前缀和,映射,数学

给定一个序列,现在问你有多少子序列,使得该子序列的所有子序列中不存在和为0的序列

如,{1,2,-3}是5个

In the first sample, the following subarrays are good: [1], [1,2], [2], [2,−3], [−3]. However, the subarray [1,2,−3] isn't good, as its subarray [1,2,−3] has sum of elements equal to 0.

思路:显然不考虑满足条件时,子序列总数量是n*(n+1)/2

接下来我们再剔除不满足条件的情况

我们可以通过前缀和与建立映射,可以知道每个和为零的子区段的始末

但是子区段之间可能有好多情况,包含,交叉,不交叉...

我们要是分析容斥性肯定不可能

但是我们可以换一种分类方法来考虑这道问题,即按照右端点情况进行分类

如果任意点x的位置n(下标为1开始计数),那么以它为右端点的子区段的数量就是n

固定x位置,分析他的左端,我们一步一步把左端向左推。一旦说左端和右端包含了一段和为0的区段,那么你左端再怎么移动,他都是不满足条件的,换言之,当我们固定x时,无非是找到所有和为0的区段中最大的左端值

这样一来无论和为0的区段如何交叉,我们都不用管,我们只要每步去更新0区段里最大的左端值即可

代码:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<map>
using namespace std;
#define INF 1e10+5
#define maxn 105
#define minn -105
#define ll long long int
#define ull unsigned long long int
#define uint unsigned int
int main()
{
    ll n,cur;
    map<ll,ll>ex;
    map<ll,ll>pos;
    ex[0]=1;
    pos[0]=0;
    cin>>n;
    ll ans=n*(n+1)/2;
    ll sum=0,curmax=0;
    for(ll i=1;i<=n;i++)
    {
        cin>>cur;
        sum+=cur;
        if(ex[sum])
        {
            curmax=max(curmax,pos[sum]+1);
        }
        ans-=curmax;
        pos[sum]=i,ex[sum]=1;
    }
    cout<<ans<<endl;
    return 0;
}
原文地址:https://www.cnblogs.com/et3-tsy/p/12664813.html