Contest1692 - 2019寒假集训第三十一场 UPC 11075 Problem D 小P的国际象棋

  非常简单的单点修改+区间加+区间查询。我用的是最近刚学的区间修改版本树状数组。
  直接维护即可,注意修改后的单点值已经不是a[i],或者b[i],要通过区间查询求单点。不然是错的。

  区间修改版本树状数组:

 

#include<iostream>
#include<string.h>
#include<stdio.h>
#include<algorithm>
#define LL long long
using namespace std;
LL c_p[400005];
LL sum_p[400005];
LL c_y[400005];
LL sum_y[400005];
LL a[200005];
LL b[200005];
int n,m;
int cnt1;
int cnt2;
int lowbit(int x){
  return x&(-x);
}
void update(int x,int w,LL c[],LL sum[]){
  for (int i=x;i<=n;i+=lowbit(i)){
     c[i]+=(LL)w;
     sum[i]+=(LL)w*(x-1);
  }
}
LL sum(int x,LL c[],LL sum[]){
   LL ans=0;
   for (int i=x;i>0;i-=lowbit(i)){
    ans+=(LL)x*c[i]-sum[i];
   }
   return ans;
}
int main(){
 
  while(~scanf("%d%d",&n,&m)){
     a[0]=0;
     cnt1=0;
     cnt2=0;
     for (int i=1;i<=n;i++){
        scanf("%lld",&a[i]);
        update(i,a[i]-a[i-1],c_p,sum_p);
     }
     b[0]=0;
     for (int i=1;i<=n;i++){
        scanf("%lld",&b[i]);
        update(i,b[i]-b[i-1],c_y,sum_y);
     }
     int ss=0;
     while(m--){
        ss++;
        char op[10];
        char to;
        int x,y,w;
        scanf("%s",op);
        if (op[1]=='i'){
            scanf(" %c",&to);
            scanf("%d%d",&x,&y);
            if (to=='P'){
                int lw=sum(x,c_p,sum_p)-sum(x-1,c_p,sum_p);
                int rw=sum(y,c_p,sum_p)-sum(y-1,c_p,sum_p);
                update(x,rw-lw,c_p,sum_p);
                update(x+1,lw-rw,c_p,sum_p);
                update(y,lw-rw,c_p,sum_p);
                update(y+1,rw-lw,c_p,sum_p);
            }else {
                int lw=sum(x,c_y,sum_y)-sum(x-1,c_y,sum_y);
                int rw=sum(y,c_y,sum_y)-sum(y-1,c_y,sum_y);
                update(x,rw-lw,c_y,sum_y);
                update(x+1,lw-rw,c_y,sum_y);
                update(y,lw-rw,c_y,sum_y);
                update(y+1,rw-lw,c_y,sum_y);
            }
        }
        else if (op[1]=='u'){
            scanf(" %c",&to);
            int l,r;
            scanf("%d%d%d",&l,&r,&w);
            if (to=='P'){
                update(l,w,c_p,sum_p);
                update(r+1,-w,c_p,sum_p);
            }else {
                update(l,w,c_y,sum_y);
                update(r+1,-w,c_y,sum_y);
            }
        }else if (op[1]=='t'){
            scanf(" %c",&to);
            scanf("%d%d",&x,&y);
            if (to=='P'){
                w=sum(x,c_y,sum_y)-sum(x-1,c_y,sum_y);
                update(x,-w,c_y,sum_y);
                update(x+1,w,c_y,sum_y);
                update(y,w,c_p,sum_p);
                update(y+1,-w,c_p,sum_p);
            }else {
                w=sum(x,c_p,sum_p)-sum(x-1,c_p,sum_p);
                update(x,-w,c_p,sum_p);
                update(x+1,w,c_p,sum_p);
                update(y,w,c_y,sum_y);
                update(y+1,-w,c_y,sum_y);
            }
        }else {
           int l,r;
           scanf("%d%d",&l,&r);
           LL num_p=sum(r,c_p,sum_p)-sum(l-1,c_p,sum_p);
           LL num_y=sum(r,c_y,sum_y)-sum(l-1,c_y,sum_y);
           if (num_p>num_y){
             cnt1++;
             printf("P %lld\n",num_p);
           }else {
             cnt2++;
             printf("Y %lld\n",num_y);
           }
        }
     }
     if (cnt1>cnt2){
        printf("little P is winner!\n");
     }else if (cnt1<cnt2){
        printf("little Y is winner!\n");
     }else {
        printf("five five open\n");
     }
  }
  return 0;
}

 

 线段树版本:。。。更新laze标记,以及sum的时候,一定要用+=,不要用=,因为往下更新的时候,有可能不为0。

 

#include<iostream>
#include<algorithm>
#include<string.h>
#include<stdio.h>
#define LL long long
using namespace std;
struct node{
  int l,r;
  LL laze;
  LL sum;
}tree[2][200005<<2];
int a[200005];
int b[200005];
int cnt1;
int cnt2;
inline int L(int r){return r<<1;};
inline int R(int r){return r<<1|1;};
inline int MID(int l,int r){return (l+r)>>1;};
void push_down(int root,node tre[]){
  if (tre[root].laze){
     tre[L(root)].laze+=tre[root].laze;
     tre[R(root)].laze+=tre[root].laze;
     tre[L(root)].sum+=(LL)tre[root].laze*(tre[L(root)].r-tre[L(root)].l+1);
     tre[R(root)].sum+=(LL)tre[root].laze*(tre[R(root)].r-tre[R(root)].l+1);
     tre[root].laze=0;
  }
}
void build(int root,int l,int r){
  tree[0][root].l=l;
  tree[1][root].l=l;
  tree[0][root].r=r;
  tree[1][root].r=r;
  tree[0][root].laze=0;
  tree[1][root].laze=0;
  tree[0][root].sum=0;
  tree[1][root].sum=0;
  if (l==r){
    tree[0][root].sum=a[l];
    tree[1][root].sum=b[l];
    return;
  }
  int mid=MID(l,r);
  build(L(root),l,mid);
  build(R(root),mid+1,r);
  tree[0][root].sum=tree[0][L(root)].sum+tree[0][R(root)].sum;
  tree[1][root].sum=tree[1][L(root)].sum+tree[1][R(root)].sum;
}
void update(int root,int ul,int ur,LL w,node tre[]){
    int l=tre[root].l;
    int r=tre[root].r;
   // cout<<l<<" "<<r<<endl;
    if (ul<=l && r<=ur){
        tre[root].sum+=(LL)(r-l+1)*w;
        tre[root].laze+=w;
        return;
    }
    push_down(root,tre);
    int mid=MID(l,r);
    if (ur<=mid)
       update(L(root),ul,ur,w,tre);
    else if (ul>mid)
       update(R(root),ul,ur,w,tre);
    else {
       update(L(root),ul,mid,w,tre);
       update(R(root),mid+1,ur,w,tre);
    }
    tre[root].sum=tre[L(root)].sum+tre[R(root)].sum;
}
LL query(int root,int ql,int qr,node tre[]){
    int l=tre[root].l;
    int r=tre[root].r;
    if (ql<=l && r<=qr){
        return tre[root].sum;
    }
    push_down(root,tre);
    int mid=MID(l,r);
    LL ans=0;
    if (qr<=mid){
        ans+=query(L(root),ql,qr,tre);
    }else if (ql>mid){
        ans+=query(R(root),ql,qr,tre);
    }else {
        ans+=query(L(root),ql,mid,tre);
        ans+=query(R(root),mid+1,qr,tre);
    }
    return ans;
}
int main(){
   int n,m;
   while(~scanf("%d%d",&n,&m)){
    for (int i=1;i<=n;i++){
        scanf("%d",&a[i]);
    }
    for (int i=1;i<=n;i++){
        scanf("%d",&b[i]);
    }
    build(1,1,n);
    cnt1=0;
    cnt2=0;
    while(m--){
       char op[10];
       char pe;
       int x,y;
       LL w;
       scanf("%s",op);
       if (op[1]=='i'){
          scanf(" %c",&pe);
          if(pe=='P'){
             scanf("%d%d",&x,&y);
             LL lw=query(1,x,x,tree[0]);
             LL rw=query(1,y,y,tree[0]);
             update(1,x,x,rw-lw,tree[0]);
             update(1,y,y,lw-rw,tree[0]);
          }else {
             scanf("%d%d",&x,&y);
             int lw=query(1,x,x,tree[1]);
             int rw=query(1,y,y,tree[1]);
             update(1,x,x,rw-lw,tree[1]);
             update(1,y,y,lw-rw,tree[1]);
          }
       }else if (op[1]=='u'){
             scanf(" %c",&pe);
             if (pe=='P'){
               scanf("%d%d%lld",&x,&y,&w);
               update(1,x,y,w,tree[0]);
             }else {
               scanf("%d%d%lld",&x,&y,&w);
               update(1,x,y,w,tree[1]);
             }
       }else if (op[1]=='t'){
             scanf(" %c",&pe);
             scanf("%d%d",&x,&y);
             if (pe=='P'){
                w=query(1,x,x,tree[1]);
                //cout<<w<<endl;
                update(1,x,x,-w,tree[1]);
                update(1,y,y,w,tree[0]);
//              for (int i=1;i<=n;i++){
//                cout<<query(1,i,i,tree[0])<<" ";
//              }
//              cout<<endl;
//               for (int i=1;i<=n;i++){
//                cout<<query(1,i,i,tree[1])<<" ";
//              }
//              cout<<endl;
             }else {
                w=query(1,x,x,tree[0]);
                update(1,x,x,-w,tree[0]);
                update(1,y,y,w,tree[1]);
             }
       }else {
          scanf("%d%d",&x,&y);
          LL sum1=query(1,x,y,tree[0]);
          LL sum2=query(1,x,y,tree[1]);
          if (sum1>sum2){
            printf("P %lld\n",sum1);
            cnt1++;
          }else {
            printf("Y %lld\n",sum2);
            cnt2++;
          }
       }
    }
    if (cnt1>cnt2){
        printf("little P is winner!\n");
    }else if (cnt1<cnt2){
        printf("little Y is winner!\n");
    }else{
        printf("five five open\n");
    }
   }
  return 0;
}
/*
5 5
1 3 2 5 1
1 3 2 5 1
mig Y 3 2
*/

 

 

 

 

posted @ 2019-02-22 23:10  bluefly-hrbust  阅读(192)  评论(0编辑  收藏  举报