2019 牛客多校 第八场

题目链接:https://ac.nowcoder.com/acm/contest/888#question 链接

 

A:(未解决)

  题意:给出一个由01组成的矩阵,求多少个最大的(不被其他的全是1子矩阵包含)全是1的子矩阵 n*n<9e6

  题解:单调队列

 

B:

  题意:求所有子区间的完美数(区间中数的种类)之和,n <1e5

  题解:方法1:求每一个数对答案的贡献,即有多少个子区间中包含这个数。

     方法2:如果n个数不同的话,总数是n*(n+1)*(n+2)/6, 在减去重复的部分。

     注意这里会算到long long,记得要乘1ll

#include<bits/stdc++.h>
using namespace std;
#define _for(i,a,b) for(int i=(a); i< (b); i++)
#define _rep(i,a,b) for(int i=(a); i<=(b); i++)
typedef long long ll;

const int MAXN=2e5+5;
int n, a[MAXN], pre[MAXN];

int main()  //方法1 
{
    cin>>n;
    _rep(i, 1, n) cin>>a[i];
    ll ans=0; 
    _rep(i, 1, n)
    {
        ans+=1ll*(i-pre[a[i]])*(n-i+1);
        pre[a[i]]=i;
    }
    cout<<ans<<endl;
    return 0;
}
/*
int main() //方法2 
{
    cin>>n;
    _rep(i, 1, n) cin>>a[i];
    ll ans=1ll*n*(n+1)*(n+2)/6;
    _rep(i, 1, n)
    {
        ans-=1ll*(n-i+1)*pre[a[i]];
        pre[a[i]]=i;
    }
    cout<<ans<<endl;
    return 0;
}
*/
View Code

 

C:

  题意:构造一个矩阵,满足任意俩行的内积是0,n=2^k (1<k<=10)

  题解:

             

    打表的过程由递归实现。

#include <bits/stdc++.h>
using namespace std; 
#define _for(i,a,b) for(int i=(a); i< (b); i++)
#define _rep(i,a,b) for(int i=(a); i<=(b); i++)
typedef long long ll; 

const int MAXN=1e3+500;
int n, a[MAXN][MAXN];
void dfs(int x, int y, int n, int v)
{
    if(n==1){
        a[x][y]=v; return;
    }
    dfs(x, y, n/2, v);
    dfs(x, y+n/2, n/2, v);
    dfs(x+n/2, y, n/2, v);
    dfs(x+n/2, y+n/2, n/2, -v);
} 

int main()
{
    dfs(1, 1, 1024, 1);
    while(cin>>n)
    {
        _rep(i,1,n) _rep(j,1,n)
            cout<<a[i][j]<<(j==n?"\n":" ");
    }
    return 0;
}
View Code

 

E:(未解决)

  题意:给出每条边的起点终点和cap的范围,求可以从1到n的cap的取值个数(整数)n,m<1e5, cap<1e9

  题解:线段树+离散化+并查集

 

G:

  题意:每三个相同消除,消除后自动相连,可以继续消除,求可以消除多少组。 n<1e5

  题解:方法1:做一个next数组标记每一个位置前面的是什么,然后比较相连的三个。

     方法2:栈模拟即可。

#include <bits/stdc++.h>
using namespace std; 
#define _for(i,a,b) for(int i=(a); i< (b); i++)
#define _rep(i,a,b) for(int i=(a); i<=(b); i++)
typedef long long ll; 

const int MAXN=2e6+5; 
char a[MAXN]; 
int cnt[MAXN], nxt[MAXN];

int main()
{
    cin>>a;
    int len=strlen(a), ans=0;
    for(int i=0; i<len; i++) cnt[i]=1;
    nxt[0]=0;
    for(int i=0; i<len; i++) nxt[i]=i-1;
    int p;
    for(int i=1; i<len; i++)
    {
        p=nxt[i];
        if(a[i]==a[p])
        {
            cnt[i]+=cnt[p];
            if(cnt[i]>=3){
                //printf("!i=%d\n", i);
                ans++;
                nxt[i+1]=nxt[nxt[p]];
                //printf("!p=%d\n", p);
            }
        }
    }
    cout<<ans<<endl;
    return 0;
}
View Code
#include <bits/stdc++.h>
using namespace std; 
#define _for(i,a,b) for(int i=(a); i< (b); i++)
#define _rep(i,a,b) for(int i=(a); i<=(b); i++)
typedef long long ll; 

const int MAXN=1e5+5; 
char a[MAXN], s[MAXN];

int main()
{
    scanf("%s", a+1);
    int n=strlen(a+1), ans=0, top=0;
    _rep(i, 1, n)
    {
        s[++top]=a[i];
        if(top>=3 && s[top]==s[top-1]&&s[top-1]==s[top-2]){
            ans++; top-=3;
        } 
    }
    cout<<ans<<endl;
    return 0;
}
View Code

 

转载于:https://www.cnblogs.com/Yokel062/p/11335446.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值