给定数列
关于本题有一些较为显然的
首先我们考虑这段区间里一定不能包含在
所以这时候我们只需要对于每个划分出来的子区间考虑其中的合法区间即可,不难想到我们要找的区间合法当且仅当里面包含了至少一个
此时考虑如何维护这四个值,显然我们可以考虑把子区间再次进行分割,遍历三次,分别由
然后还有个点就是如果
xxxxxxxxxx
931
2
3
4
5
6
7
8
9
10
11using namespace std;
12using namespace __gnu_pbds;
13
14mt19937 rnd(random_device{}());
15int rndd(int l, int r){return rnd() % (r - l + 1) + l;}
16bool rnddd(int x){return rndd(1, 100) <= x;}
17
18typedef unsigned int uint;
19typedef unsigned long long unll;
20typedef long long ll;
21typedef long double ld;
22
23template< typename T = int >
24inline T read(void);
25
26int N, X, Y;
27int a[210000];
28int cnt0(0), cnt1(0), cnt_1(0), l(1), r(-1);
29ll ans(0);
30
31ll GetC(int n, int m){
32 if(n == 1)return 1;
33 if(!n || m > n)return 0;
34 ll ret(1);
35 for(int i = n; i >= n - m + 1; --i)ret *= i;
36 for(int i = m; i >= 1; --i)ret /= i;
37 return ret + n;
38}
39
40int main(){
41 N = read(), X = read(), Y = read();
42 for(int i = 1; i <= N + 1; ++i){
43 a[i] = i <= N ? read() : INT_MAX;
44 a[i] = a[i] == X && a[i] == Y ? -114514 : (a[i] == X ? 1 : (a[i] == Y ? -1 : (Y <= a[i] && a[i] <= X ? 0 : 114514)));
45 if(a[i] != 114514){r = i; continue;}
46 if(!~r){l = i + 1; continue;}
47 ll cur(0);
48 cur += GetC(r - l + 1, 2);
49 int ll(l), rr(-1);
50 for(int j = l; j <= r; ++j){
51 if(a[j] != -1 && a[j] != -114514){rr = j; continue;}
52 if(!~rr){ll = j + 1; continue;}
53 cur -= GetC(rr - ll + 1, 2);
54 ll = j + 1;
55 }if(ll <= rr)cur -= GetC(rr - ll + 1, 2);
56 ll = l, rr = -1;
57 for(int j = l; j <= r; ++j){
58 if(a[j] != 1 && a[j] != -114514){rr = j; continue;}
59 if(!~rr){ll = j + 1; continue;}
60 cur -= GetC(rr - ll + 1, 2);
61 ll = j + 1;
62 }if(ll <= rr)cur -= GetC(rr - ll + 1, 2);
63 ll = l, rr = -1;
64 for(int j = l; j <= r; ++j){
65 if(!a[j]){rr = j; continue;}
66 if(!~rr){ll = j + 1; continue;}
67 cur += GetC(rr - ll + 1, 2);
68 ll = j + 1;
69 }if(ll <= rr)cur += GetC(rr - ll + 1, 2);
70 ans += cur;
71 l = i + 1;
72 }
73 printf("%lld\n", ans);
74
75 fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);
76 return 0;
77}
78
79template < typename T >
80inline T read(void){
81 T ret(0);
82 short flag(1);
83 char c = getchar();
84 while(c != '-' && !isdigit(c))c = getchar();
85 if(c == '-')flag = -1, c = getchar();
86 while(isdigit(c)){
87 ret *= 10;
88 ret += int(c - '0');
89 c = getchar();
90 }
91 ret *= flag;
92 return ret;
93}
然后因为我是完全按照这个思路实现的所以上面的可能非常丑,所以这里也贴一个 @Zpair 的优美实现。
xxxxxxxxxx
181
2using namespace std;
3typedef long long ll;
4int l1,l2,l3,l4,n,x,y;ll ans;
5ll get(int x){return (ll)x*(x+1)/2;}
6int main(){
7 cin>>n>>x>>y;int v;
8 for(int i=1;i<=n;++i){
9 scanf("%d",&v);
10 if(v>x||v<y){ans+=get(l1)-get(l2)-get(l3)+get(l4),l1=l2=l3=l4=0;continue;}
11 if(v!=x&&v!=y)l1++,l2++,l3++,l4++;
12 if(v==x&&v==y)l1++,ans+=-get(l2)-get(l3)+get(l4),l2=l3=l4=0;
13 if(v==x&&v!=y)l1++,l3++,ans+=-get(l2)+get(l4),l2=l4=0;
14 if(v!=x&&v==y)l1++,l2++,ans+=-get(l3)+get(l4),l3=l4=0;
15 }
16 ans+=get(l1)-get(l2)-get(l3)+get(l4);
17 cout<<ans;
18}
update-2022_10_24 初稿