思维题
又是一道完全不会的题qwq
将一条链划分成若干个联通块,其实就是划分成一些区间。每个区间都会有左端点和右端点,且当一个点作为左端点的时候,必定有一个点作为右端点(都是废话)
那么我们只要把每个点能作为左端点的区间数加起来就是答案啦,右端点的就不用统计了,因为每一个点作为左端点都对应了另一个点作为右端点。
如果val[i - 1] > val[i],那么可以组成的区间要满足1 <= l <= val[i] <= r < val[i - 1],算出来的答案就是 val[i] * (val[i - 1] - val[i])
如果val[i - 1] < val[i],那么可以组成的区间要满足val[i - 1] < l <= val[i] <= r <= n,算出来的答案就是 (val[i] - val[i - 1]) * (n - val[i] + 1)
#include <bits/stdc++.h> #define INF 0x3f3f3f3f #define full(a,b) memset(a,b,sizeof a) using namespace std; typedef long long ll; inline int lowbit(int x){ return x & (-x); } inline int read(){ int X = 0,w = 0; char ch = 0; while(!isdigit(ch)) { w |= ch == '-'; ch = getchar(); } while(isdigit(ch)) X = (X << 3) + (X << 1) + (ch ^ 48),ch = getchar(); return w ? -X : X; } inline int gcd(int a,int b){ return a % b ? gcd(b,a % b) : b; } inline int lcm(int a,int b){ return a / gcd(a,b) * b; } template<typename T> inline T max(T x,T y,T z){ return max(max(x,y),z); } template<typename T> inline T min(T x,T z){ return min(min(x,z); } template<typename A,typename B,typename C> inline A fpow(A x,B p,C lyd){ A ans = 1; for(; p; p >>= 1,x = 1LL * x * x % lyd)if(p & 1)ans = 1LL * x * ans % lyd; return ans; } const int N = 100005; int a[N],n; ll ans; int main(){ ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr); cin >> n; for(int i = 1; i <= n; i ++) cin >> a[i]; ans += 1LL * a[1] * (n - a[1] + 1); for(int i = 2; i <= n; i ++){ if(a[i] < a[i - 1]) ans += 1LL * a[i] * (a[i - 1] - a[i]); else if(a[i] > a[i - 1]) ans += 1LL * (a[i] - a[i - 1]) * (n - a[i] + 1); } cout << ans << endl; return 0; }
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。