无题

大讨论题。。写了一点就弃疗了。。按权值大小枚举中间那个数,根据两边的值与中间那个值得大小关系可以分出3类,反过来又是三类,一共九类。。

发现每个位置的贡献最多变化两次。。。发现要取最值不能离散化就弃疗了。。

 记个题号以后再补吧。。bzoj1099

  1 #include <bits/stdc++.h>
  2 
  3 using namespace std;
  4 typedef long long ll;
  5 const int N = 50100;
  6 struct Node{
  7     int x,y;
  8     Node(){}
  9     Node(int x,int y):x(x),y(y){}
 10 }nod[N];
 11 ll seg[3][N<<2],sum[3][N<<2];
 12 int n,a[N],rank[N],len,finger;
 13 ll sum,ans[N];
 14 bool cmp(const Node &a,const Node &b){
 15     return a.x < b.x;
 16 }
 17 void init();
 18 void insert(int,int,int,int,int,int);
 19 void update(int,int);
 20 int main(){
 21     scanf("%d",&n);
 22     for (int i = 1;i <= n;i++) scanf("%d",&a[i]);
 23     for (int i = 1;i < n;i++) sum += abs(a[i]-a[i+1]);
 24     if (n == 2){
 25         printf("%lld\n%lld\n",sum,sum);
 26         return 0;
 27     }
 28     init();
 29     
 30     for (int i = 2;i < n;i++)
 31         nod[i] = Node(a[i],i);
 32     sort(nod+2,nod+n,cmp);
 33     
 34     len = 1;
 35     for (int i = 3;i < n;i++)
 36         if (nod[i].x != nod[i-1].x) rank[i-1] = len++;
 37         else rank[i-1] = len;
 38     rank[n-1] = len;
 39     
 40     finger = nod[2].x;
 41     for (int i = 2;i < n;i++){
 42         if (abs(nod[i].y-nod[2].y) != 1){
 43             int opt;
 44             if (min(a[nod[i].y-1],a[nod[i].y+1]) >= nod[2].x) opt = 0;
 45             else if (max(a[nod[i].y-1],a[nod[i].y+1) <= nod[2].x) opt = 2;
 46             else opt = 1;
 47             insert(1,1,n,rank[nod[i].y],nod[i].y,opt);
 48         }
 49     }
 50     for (int i = 2;i < n;i++){
 51         int l = rank[nod[i].y-1],r = rank[nod[i].y+1];
 52         if (l > r) swap(l,r);
 53         ll w1 = getans(1,1,n,1,l,0)-nod[i].x*2+a[nod[i].y-1]+a[nod[i].y+1];
 54         ll w2 = getans(1,1,n,l,r,0)-nod[i].x*2+abs(a[nod[i].y-1]-a[nod[i].y+1]);
 55     }
 56     for (int i = 1;i <= n;i++) printf("%d\n",sum+min(0,ans[i]));
 57     return 0;
 58 }
 59 void init(){
 60     for (int i = 2;i < n-1;i++){
 61         ll w = abs(a[i]-a[i+2])+abs(a[i-1]-a[i+1])-abs(a[i]-a[i-1])-abs(a[i+1]-a[i+2]);
 62         ans[i] = min(ans[i],w);
 63         ans[i+1] = min(ans[i+1],w);
 64     }
 65     
 66     for (int i = 2;i < n-1;i++){
 67         ll w = abs(a[i+1]-a[1])+abs(a[i-1]-a[1])+abs(a[2]-a[i])-abs(a[2]-a[1])-abs(a[i-1]-a[i])-abs(a[i+1]-a[i]);
 68         ans[1] = min(ans[1],w);
 69         ans[i] = min(ans[i],w);
 70         w = abs(a[i+1]-a[n])+abs(a[i-1]-a[n])+abs(a[n-1]-a[i])-abs(a[n-1]-a[n])-abs(a[i-1]-a[i])-abs(a[i+1]-a[i]);
 71         ans[n] = min(ans[n],w);
 72         ans[i] = min(ans[i],w);
 73     }
 74         
 75     ll w = abs(a[2]-a[n])+abs(a[1]-a[n-1])-abs(a[1]-a[2])-abs(a[n]-a[n-1]);
 76     ans[1] = min(ans[1],w);
 77     ans[n] = min(ans[n],w);
 78     w = abs(a[3]-a[1])-abs(a[3]-a[2]);
 79     ans[1] = min(ans[1],w);
 80     ans[2] = min(ans[2],w);
 81     w = abs(a[n-2]-a[n])-abs(a[n-2]-a[n-1]);
 82     ans[n] = min(ans[n],w);
 83     ans[n-1] = min(ans[n-1],w);
 84 }
 85 void insert(int p,int l,int r,int x,int y,int opt){
 86     if (l == r){
 87         sum[opt][l] += a[y];
 88         if (opt == 0) seg[opt][l] += a[y-1]+a[y+1];
 89         if (opt == 1) seg[opt][l] += abs(a[y-1]-a[y+1]);
 90         if (opt == 2) seg[opt][l] -= a[y-1]+a[y+1];
 91         return;
 92     }
 93     int mid = l + r >> 1;
 94     if (x <= mid) insert(p<<1,l,mid,x,y,opt);
 95     else insert(p<<1|1,mid+1,r,x,y,opt);
 96     update(p,opt); 
 97 }
 98 void update(int p,int opt){
 99     int u = p<<1,v = u|1;
100     sum[opt][p] = sum[opt][u]+sum[opt][v];
101     seg[opt][p] = seg[opt][u]+seg[opt][v];
102 }

 

posted @ 2017-07-03 20:44  VictBr  阅读(118)  评论(0编辑  收藏  举报