【線段樹提高】51nod &&洛谷

ACM_e發表於2018-07-10

兩個線段樹很好的題目

NO.1 51nod  1426 沙拉醬括號

點選這裡即可

好多都用字首和+二分 我覺得線段樹可行做了一下  就是要用vc++ 交C語言 不然會t

#include<stdio.h>
#include<algorithm>
#include<cmath>
#include<cstring>
//using namespace std;
#define maxn 8000000+100
int aa[maxn];
int min(int x,int y){
  if(x>=y) return y;
  return x;
}
struct ac{
  int s,l,r;
  ac(){
    s=0;l=0,r=0;
  }
  ac(int a,int b,int c){
     s=a,l=b,r=c;
  }
}a[maxn*4];
void build(int l,int r,int in){
  if(l==r){
     if(aa[l]==1)
      a[in]=ac(0,1,0);
     else a[in]=ac(0,0,1);
     return ;
  }
  int mid=(l+r)/2;
  build(l,mid,in*2);
  build(mid+1,r,in*2+1);
  int lson=in*2,rson=in*2+1;

  int x=min(a[lson].l,a[rson].r);

  int y=a[lson].l-x;int z=a[rson].r-x;

  int s=a[lson].s+a[rson].s+x;

  a[in]=ac(s,y+a[rson].l,a[lson].r+z);
}
ac query(int l,int r,int L,int R,int in){
   if(l==L&&r==R){
      return a[in];
   }
   int mid=(l+r)/2;
   if(L>mid){         //這個地方一定要處理好 因為我返回的是結構體所以返回的含有這個區間左右括號的資訊
      return query(mid+1,r,L,R,in*2+1);
   }else if(R<=mid){
      return query(l,mid,L,R,in*2);
   }
   ac b=query(l,mid,L,mid,in*2);

   ac c=query(mid+1,r,mid+1,R,in*2+1);

   int x=min(b.l,c.r);

   int y=b.l-x;int z=c.r-x;

   int k=b.s+c.s+x;

   return ac(k,y+c.l,b.r+z);
}
int main(){
   char s[maxn*10];
   scanf("%s",s);
   int n;
   scanf("%d",&n);
   int len=strlen(s);
   for(int j=0;j<len;j++){
      if(s[j]=='(')
       aa[j+1]=1;
      else aa[j+1]=-1;
   }
   build(1,len,1);
   for(int j=0;j<n;j++){
      int l,r;
      scanf("%d%d",&l,&r);
      ac b=query(1,len,l,r,1);
      printf("%d\n",b.s*2);
   }

   return 0;
}

洛谷 3797 妖夢斬木棒

點選這裡即可

#include<bits/stdc++.h>
using namespace std;
#define maxn 600000+100//結構體消耗記憶體好大 我開了這麼大才可以 小的話後面的資料全部 re
struct ac{
  int s,l,r; //(l=='('  r==')';
  ac(){
    s=0;
    l=0;
    r=0;
  }
  ac(int a,int b,int c){
     s=a;
     l=b;
     r=c;
  }
}a[maxn*4];
int n,m;
void updata(int l,int r,int in,int va,int v){
   if(r<1|r>n) return ;
   if(l==r){
      if(v==1) a[in]=ac(0,1,0);  
      if(v==2) a[in]=ac(0,0,1);
      if(v==3) a[in]=ac(0,0,0); //更新不多解釋
      return ;
   }
   int mid=(l+r)/2;
   if(va>mid){
      updata(mid+1,r,in*2+1,va,v);
   }else{
      updata(l,mid,in*2,va,v);
   }
   int x=a[in*2].s+a[in*2+1].s;
   int y=a[in*2].l+a[in*2+1].r;            // 看左右能否組成一個完整的括號
   if(y==2){
     a[in]=ac(x+1,a[in*2+1].l,a[in*2].r); //可以組成採用右兒子的左括號,左兒子的右括號
   }else{
     if(x!=0){  //當他們存在完整的括號對時 
       if(a[in*2].s==0&&a[in*2].r==0){    // 完整的括號對在右區間的時候
          a[in]=ac(x,a[in*2+1].l,a[in*2+1].r);
       }else if(a[in*2+1].s==0&&a[in*2+1].l==0){  //在左區間的時候
          a[in]=ac(x,a[in*2].l,a[in*2].r);
       }
       else a[in]=ac(x,a[in*2+1].l,a[in*2].r); //左右區間都存在
     }
     else a[in]=ac(x,a[in*2+1].l|a[in*2].l,a[in*2+1].r|a[in*2].r);//左右都不存在
   }
}
ac query(int l,int r,int L,int R,int in){
   if(l==L&&r==R){
      return a[in];
   }
   int mid=(l+r)/2;
   if(L>mid){         //這個地方一定要處理好 因為我返回的是結構體所以返回的含有這個區間左右括號的資訊
      return query(mid+1,r,L,R,in*2+1);
   }else if(R<=mid){
      return query(l,mid,L,R,in*2);
   }        
   //下面和更新操作的一樣 
   ac b=query(l,mid,L,mid,in*2);
   ac c=query(mid+1,r,mid+1,R,in*2+1);
   int x=b.s+c.s;
   int y=b.l+c.r;
   if(y==2){
     return ac(x+1,c.l,b.r);
   }
   if(x!=0){
       if(b.s==0&&b.r==0){
          return ac(x,c.l,c.r);
       }else if(c.s==0&&c.l==0){
          return ac(x,b.l,b.r);
       }
       return ac(x,a[in*2+1].l,a[in*2].r);
     }
   return ac(x,c.l|b.l,c.r|b.r);
}
int main(){
 // FILE *fp;
 // fp=fopen("C://Users//Dcoder//Desktop//1.txt","r+");
   cin>>n>>m;
   //build(1,n,1);
   updata(1,n,1,1,1);//相當於兩次更新 一次開頭 一次結尾
   updata(1,n,1,n,2);
   while(m--){
      int x;
      cin>>x;
      if(x==2){
         int l,r;
         cin>>l>>r;
       //  fprintf(fp,"%d\n",query(1,n,l,r,1).s);
         cout<<query(1,n,l,r,1).s<<endl;
      }else{
         char c;
         int y;
         cin>>y>>c;
         if(c=='X'){
            updata(1,n,1,y,3);
         }else if(c=='('){
            updata(1,n,1,y,1);
         }else{
            updata(1,n,1,y,2);
         }
      }
   }
   //fclose(fp);
   return 0;
}


相關文章