Command Sequence

传送门

思路

不妨令:
num_U:字符‘U’的数目
num_D:字符‘D’的数目
num_L:字符‘L’的数目
num_R:字符‘R’的数目
我们称呼区间内 num_U 等于 num_D 且 num_L 等于 num_R 的连续区间 [l,r] 为 ”好区间“
给定我们一个只由 ‘U’ ‘D’ ‘L’ ‘R’ 四种字符组成的字符串,问:这样的“好区间”有多少个 ?

对于好区间 [l,r],显然有:
sum_U[r] - sum_U[l-1] = sum_D[r] - sum_D[l-1]
sum_L[r] - sum_L[l-1] = sum_R[r] - sum_R[l-1]
转化得:
sum_U[r] - sum_D[r] = sum_U[l-1] - sum_D[l-1]
sum_R[r] - sum_L[r] = sum_R[l-1] - sum_L[l-1]

所以我们不妨枚举区间右端点 r ,看有几个左端点可以与 r 构成“好区间”,然后累加,最后得到答案

那么如何判断 左端点 l 是否可以与 右端点 r 构成“好区间” 呢 ?
因为 “好区间”的 l 与 r 满足:
sum_U[r] - sum_D[r] = sum_U[l-1] - sum_D[l-1] 且 sum_R[r] - sum_L[r] = sum_R[l-1] - sum_L[l-1]

而对于 r 已经有了:first:sum_U[r] - sum_D[r] 和 second:sum_R[r] - sum_L[r]
所以,我们只需要统计 r 前 ,sum_U[i]- sum_D[i] = first 且 sum_R[i] - sum_L[i] = second 的点数既可

我们可以用 map 与 pair 来辅助我们,这更加方便

Code

#include <bits/stdc++.h>

using namespace std;

typedef pair<int,int> PII;
typedef long long ll;

const int N = 1e5+10;

PII p[N];
char s[N];
map<PII,ll> ma;
int sum_L[N],sum_R[N];
int sum_U[N],sum_D[N];
int n;

int main(){
    int T;
    scanf("%d",&T); 
    
    while(T--){
        map<PII,ll>tmpp;
        ma.swap(tmpp);
        scanf("%d",&n);
        scanf("%s",s+1);
        for(int i=1;i<=n;i++){
            sum_U[i]=sum_U[i-1];
            sum_D[i]=sum_D[i-1];
            sum_L[i]=sum_L[i-1];
            sum_R[i]=sum_R[i-1];
            if(s[i]=='U') sum_U[i]++;
            else if(s[i]=='D') sum_D[i]++;
            else if(s[i]=='L') sum_L[i]++;
            else if(s[i]=='R') sum_R[i]++;
        }
        
        for(int i=1;i<=n;i++){
            p[i].first=sum_R[i]-sum_L[i];
            p[i].second=sum_U[i]-sum_D[i];
        }
        
        PII x;
        x.first=x.second=0;
        ma[x]++;
        ll res=0;
        for(int i=1;i<=n;i++){  // 枚举右端点
            res+=ma[p[i]];   // 累加合法的左端点数目
            ma[p[i]]++;
        }
        printf("%lld\n",res);
    }
    
    return 0;
} 
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值