您的位置:首页 > 其它

[Codeforces] #441 div.2

2017-10-16 21:57 357 查看

A. Trip For Meal

给 n a b c,分别表示一个数 n 和一个三角形的三边

你被要求从这个三角形的 a 和 b 的交点出发,在这个三角形上以最小距离走 n-1 步

那么这个,,,,

如果 a 或 b 是最短边的话,我们在单条边上抽搐 n-1 次即可

否则 c 就是最短边了

我们通过 a 或 b (哪条短啊qwq)走到 c 前

然后在 c 上抽搐 n-2 次

这很显然qwq 注意特判 n == 1

#include<cstdio>
#include<iostream>
using namespace std;

int n,arr[505050],max_num,s_poi,stack[505050];
int L[505050],R[505050],uL[505050],uR[505050];
int pos,iL[505050][32],iR[505050][32],inf = 1e9;
long long ans = 0;

int main(){
scanf("%d",&n);

for(int i = 1;i <= n;i++){
scanf("%d",&arr[i]);
max_num = max(arr[i],max_num);
}

for(int i = 1;i <= n;i++){
while(s_poi && arr[stack[s_poi-1]] <= arr[i])
R[stack[s_poi-1]] = i-1,
s_poi--;
stack[s_poi++] = i;
}while(s_poi) R[stack[--s_poi]] = n;

for(int i = n;i >= 1;i--){
while(s_poi && arr[stack[s_poi-1]] < arr[i])
L[stack[s_poi-1]] = i+1,
s_poi--;
stack[s_poi++] = i;
}while(s_poi) L[stack[--s_poi]] = 1;

int len = 0;
for(int i = max_num;i;i >>= 1)
len++;

for(int j = 1;j <= len;j++){
pos = 0;
for(int i = 1;i <= n;i++){
if(arr[i] & (1<<(j-1))) pos = i,iL[i][j] = 0;
else iL[i][j] = pos;
}pos = n+1;
for(int i = n;i >= 1;i--){
if(arr[i] & (1<<(j-1))) pos = i,iR[i][j] = n+1;
else iR[i][j] = pos;
}
}
//    for(int j = len;j >= 1;j--){
//        for(int i = 1;i <= n;i++)
//            printf("%d/%d ",iL[i][j],iR[i][j]);
//            puts("");
//    }

for(int i = 1;i <= n;i++){
uL[i] = 0,uR[i] = n+1;
for(int j = 1;j <= len;j++)
uL[i] = max(uL[i],iL[i][j]),
uR[i] = min(uR[i],iR[i][j]);
}

//    for(int i = 1;i <= n;i++){
//        printf("%d %d %d %d\n",L[i],uL[i],uR[i],R[i]);
//    }

for(int i = 1;i <= n;i++){
ans += max(0LL,1LL*(uL[i]-L[i]+1)*(R[i]-i+1))+max(0LL,1LL*(i-L[i]+1)*(R[i]-uR[i]+1));
ans -= max(1LL*(R[i]-uR[i]+1)*(uL[i]-L[i]+1),0LL);
//        printf("\n",1LL*(uL[i]-L[i]+1)*(R[i]-i+1),1LL*(i-L[i]+1)*(R[i]-uR[i]+1),1LL*(R[i]-uR[i]+1)*(uL[i]-L[i]+1),ans);
}

cout << max(ans,0LL) << endl;

return 0;
}
F.

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: