NBUT 1120 Reimu's Teleport (线段树)

 

题意:有n个格子,一开始全部面向top。接下来的每次修改F a b ,如果 a>b则将a~b之间的格子全面置为向右,否则置为向左。对于每个询问Q输出向左、top、右的数量。

思路:普通线段树。每个结点中保存三个值,分别对应3个方向的数量。要设置一下lazy_tag以减少时间消耗,因为有可能Q远少于F,那么一直在更改,大多可能不需要改到,暂时不更新,询问时要用到再更新。每次一改就整个区间都是一个方向,所以当有tag时可以往下推各占多少。

  1 #include<bits/stdc++.h>

  2 using namespace std;

  3 int ans[3];//答案

  4 struct node

  5 {

  6     bool tag;

  7     int num[3];

  8     node *ll,*rr;

  9     node()

 10     {

 11         tag=false;

 12         num[0]=num[1]=num[2]=0;

 13         ll=rr=0;

 14     }

 15 };

 16 

 17 node * built(int LL, int RR)

 18 {

 19     node *tmp=new(node);

 20     if(LL==RR)

 21     {

 22         tmp->num[1]=1;

 23         return tmp;

 24     }

 25     int mid=(LL+RR)>>1;

 26     tmp->ll=built(LL,mid);

 27     tmp->rr=built(mid+1,RR);

 28     tmp->num[1]+=tmp->ll->num[1]+tmp->rr->num[1];   //开始只需要更新向上的

 29     return tmp;

 30 }

 31 

 32 void modify( node *t,int LL,int RR,int mid)//专门修改统计数量

 33 {

 34     if(t->num[0])

 35     {

 36         t->ll->num[0]=mid+1-LL;

 37         t->ll->num[1]=t->ll->num[2]=0;

 38         t->rr->num[0]=RR-mid;

 39         t->rr->num[1]=t->rr->num[2]=0;

 40     }

 41     if(t->num[1])

 42     {

 43         t->ll->num[1]=mid+1-LL;

 44         t->ll->num[0]=t->ll->num[2]=0;

 45         t->rr->num[1]=RR-mid;

 46         t->rr->num[0]=t->rr->num[2]=0;

 47     }

 48     if(t->num[2])

 49     {

 50         t->ll->num[2]=mid+1-LL;

 51         t->ll->num[0]=t->ll->num[1]=0;

 52         t->rr->num[2]=RR-mid;

 53         t->rr->num[0]=t->rr->num[1]=0;

 54     }

 55 }

 56 

 57 void update(int ll,int rr,int LL,int RR,int c,node *t)

 58 {

 59     if(ll==LL&&rr==RR)

 60     {

 61         t->tag=true;

 62         if(c==0)

 63         {

 64             t->num[0]=RR-LL+1;

 65             t->num[1]=t->num[2]=0;

 66         }

 67         else

 68         {

 69             t->num[2]=RR-LL+1;

 70             t->num[0]=t->num[1]=0;

 71         }

 72         return;

 73     }

 74     int mid=(LL+RR)>>1;

 75 

 76     if(t->tag)

 77     {

 78         t->tag=false;

 79         t->ll->tag=t->rr->tag=true;

 80         modify(t,LL,RR,mid);

 81     }

 82     if(ll>mid)  //右边

 83         update(ll,rr,mid+1,RR,c,t->rr);

 84     else if(rr<=mid)    //左边

 85         update(ll,rr,LL,mid,c,t->ll);

 86     else

 87     {

 88         update(ll, mid, LL, mid, c,t->ll);

 89         update(mid+1,rr,mid+1,RR,c,t->rr);

 90     }

 91     t->num[0]=t->ll->num[0]+t->rr->num[0];

 92     t->num[1]=t->ll->num[1]+t->rr->num[1];

 93     t->num[2]=t->ll->num[2]+t->rr->num[2];

 94 }

 95 

 96 

 97 

 98 void query(int ll,int rr,int LL,int RR,node* t)

 99 {

100     if(ll==LL && rr==RR)

101     {

102         ans[0]+=t->num[0];

103         ans[1]+=t->num[1];

104         ans[2]+=t->num[2];

105         return;

106     }

107     int mid=((LL+RR)>>1);

108     if(t->tag)

109     {

110         t->tag=false;

111         t->ll->tag= t->rr->tag= true;

112         modify(t, LL, RR, mid);

113     }

114 

115     if(ll>mid)          query(ll,rr,mid+1,RR,t->rr);

116     else if(rr<=mid)    query(ll,rr,LL,mid,t->ll);

117     else

118     {

119         query(ll, mid, LL, mid, t->ll);

120         query(mid+1,rr,mid+1,RR,t->rr);

121     }

122 

123 }

124 

125 

126 int main()

127 {

128     //freopen("e://input.txt","r",stdin);

129     int a, t, e, r;

130     char ch;

131 

132     while(cin>>a>>t)

133     {

134         node *tree=built(1,t); //建树

135 

136         for(int i=0; i<a; i++)

137         {

138             cin>>ch;

139             scanf("%d %d", &e, &r);

140             if(ch=='F')  //修改

141             {

142                 if(e>r) update(r, e, 1, t, 0, tree);

143                 else    update(e, r, 1, t, 2, tree);

144             }

145             else        //Q 查询

146             {

147                 memset(ans,0,sizeof(ans));

148                 query(e,r,1,t,tree);

149                 printf("%d %d %d\n",ans[0],ans[1],ans[2]);

150             }

151         }

152     }

153     return 0;

154 }
AC代码

 

你可能感兴趣的:(port)