D. Constant Palindrome Sum(线段树区间更新)

http://codeforces.com/contest/1343/problem/D

题意:

数组n,每个数 [ 1 , k ] \in[1,k] 。现在要求变化最少的数,使得:

  • 每个数 [ 1 , k ] \in[1,k]
  • 对于所有的 i i a [ i ] + a [ n i + 1 ] a[i]+a[n-i+1] 相同

解析:

对于每个 i ( i n / 2 ) i(i\leq n/2) ,对 a [ i ] + a [ n i + 1 ] a[i]+a[n-i+1] 的位置贡献为0,假设可以一次到达的区间为 [ L , R ] [L,R] ,对 [ L , R ] [L,R] 的位置贡献为1,其他位置为2。

最后求一个最小值。

解析:

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<math.h>
#include<algorithm>
#include<limits.h>
using namespace std;
#define rep(i,a,b) for(register int i=a;i<=b;i++)
#define lson (rt<<1)
#define rson ((rt<<1)|1)
#define mid (l+r>>1)
const int maxn=4e5+9;
int n;

//*********此模板(rt,l,r)==(1,1,n)******************
int trmin[maxn<<2];
int laz[maxn<<2];
void build(int rt,int l,int r){
    trmin[rt]=laz[rt]=0;
    if(l==r){return;}
    build(lson,l,mid);
    build(rson,mid+1,r);
}
void pushdown(int rt){
    if(laz[rt]){
        trmin[lson]+=laz[rt];
        trmin[rson]+=laz[rt];
        laz[lson]+=laz[rt];
        laz[rson]+=laz[rt];
        laz[rt]=0;
    }
}
void update(int rt,int l,int r,int L,int R,int Val){
    if(L<=l&&R>=r){
        trmin[rt]+=Val;
        laz[rt]+=Val;
        return;
    }
    pushdown(rt);
    if(L<=mid)update(lson,l,mid,L,R,Val);
    if(R>mid) update(rson,mid+1,r,L,R,Val);
    trmin[rt]=min(trmin[lson],trmin[rson]);
}

int a[maxn];

int main(){
    int t;scanf("%d",&t);
    while(t--){
        int n,k;
        scanf("%d%d",&n,&k);
        rep(i,1,n){
            scanf("%d",a+i);
        }
        build(1,1,2*k);
        rep(i,1,n/2){
            int op=a[i]+a[n-i+1];
            int l=max(1,op-max(a[i]-1,a[n-i+1]-1));
            int r=min(2*k,op+max(k-a[i],k-a[n-i+1]));
//            printf("--%d  %d %d\n",op,l,r);
            update(1,1,2*k,1,2*k,2);
            update(1,1,2*k,l,r,-1);
            update(1,1,2*k,op,op,-1);
        }
        printf("%d\n",trmin[1]);
    }
}
/*
1
6 6
5 2 6 1 3 4
*/

发布了790 篇原创文章 · 获赞 348 · 访问量 22万+

猜你喜欢

转载自blog.csdn.net/jk_chen_acmer/article/details/105691822
今日推荐