JMS NO.1 SCHOOL TEXT 3

JMS NO.1 SCHOOL TEXT 3

Problem. A

题目描述

给定两个长度相等的字符串,保证字符串之间差奇数个,请求出排中间的字符串是多少

输入格式

第一行,一个正整数n表示字符串长度

接下来2行,表示两个长度为n的字符串

输出格式

一行,表示位于中间的字符串

输入样例

2

az

bf

输出样例

bc

数据范围

对于前50%   n<=1,000

对于 100%   n<=200,000

 





标程:

Problem. B





题目描述

给定n个数,问最少选几个数,使他们的gcd1

输入格式

第一行一个正整数n

第二行,共n个数表示ai

输出格式

       输出 1 行,表示答案,若不存在则输出-1

输入样例

       3

10 6 15  

输出样例

3

数据范围

       对于40%  保证 n<=20

       对于另外20%  保证 n<=1000ai<=2000

       对于100% 保证 1<=n,ai<=300000

 

 



标程:

Problem. C





题目描述

 n本书,第 i 本书中有 ai 个问题,均属于第 ti 类问题。

 q 次询问,每次询问给出一个区间 [li,ri] ,询问有多少个原序列的连续子区间是给出区间的子区间,且该子区间中所有书中问题的和满足第 1 类的问题恰好比第 2 类的问题恰好多 k 个。

输入格式

       第一行,两个正整数nk

       第二行,共n个数,表示ti

       第三行,共n个数,表示ai

第四行,一个正整数q

接下来q行,每行两个数liri

输出格式

       q行,表示答案

输入样例

       4 1

1 1 1 2

1 1 1 1

4

1 2

1 3

1 4

3 4

输出样例

       2

3

4

1

数据范围

       20 % n,q<=10

50 % n,q<=2,000

100 % n,q<=100,0000<=ai<=1e91<=ti<=2-1e9<=k<=1e9

 

 

 

 



标程:

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int MAXN = 110000;

int n,q,Q;
int t[MAXN],a[MAXN];
ll k,sum[MAXN],A[MAXN],B[MAXN];// A -> -k / B -> +k
map<ll,int> S;int tmpcnt = 0;

struct Query{
int l,r,id;
}qu[MAXN];

bool cmp(Query a,Query b){
 if(a.l/Q != b.l/Q)
 return a.l / Q < b.l / Q;
else
return ((a.l/Q)&1)?a.r < b.r:a.r > b.r;
}

void init(){
scanf("%d %lld",&n,&k);
for(int i = 1;i<=n;i++) scanf("%d",&t[i]);
 for(int i = 1;i<=n;i++) scanf("%d",&a[i]);
 for(int i = 1;i<=n;i++){
 sum[i] = t[i] == 1?a[i]:-a[i];
 sum[i] += sum[i-1];
	S[sum[i]] = 0;
  }
 S[0] = 0;
 for(auto it = S.begin();it != S.end();it++)
 it->second = ++tmpcnt;
  for(int i = 0;i<=n;i++){
  if(S.count(sum[i]-k)) A[i] = S[sum[i]-k];
   if(S.count(sum[i]+k)) B[i] = S[sum[i]+k];
   sum[i] = S[sum[i]];
  }
  Q = sqrt(n);
  scanf("%d",&q);
 for(int i = 1;i<=q;i++)
    scanf("%d %d",&qu[i].l,&qu[i].r),qu[i].id = i;
 sort(qu+1,qu+q+1,cmp);
   }

static int cnt[MAXN],L = 1,R = 0;// cnt 维护 [L-1,R] 的前缀和
ll ans = 0;
void addL(int pos){
    ans += cnt[B[pos-1]];cnt[sum[pos-1]]++;
}
void addR(int pos){
    ans += cnt[A[pos]];cnt[sum[pos]]++;
}
void delL(int pos){
    cnt[sum[pos-1]]--;ans -= cnt[B[pos-1]];
}
void delR(int pos){
    cnt[sum[pos]]--;ans -= cnt[A[pos]];
}

ll ANS[MAXN];

void solve(){
    cnt[S[0]] = 1;
for(int i = 1;i<=q;i++){
    while(qu[i].l < L) addL(--L);
    while(qu[i].r > R) addR(++R);
    while(qu[i].l > L) delL(L++);
    while(qu[i].r < R) delR(R--);
    ANS[qu[i].id] = ans;
}
for(int i = 1;i<=q;i++){
    printf("%lld\n",ANS[i]);
}
}

int main(){
init();
solve();
return 0;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值