NOIP模拟题 2015.8.9 T3
NOIP模拟题 2015.8.16 T3

NOIP模拟题 2015.8.10 T3

HJWJBSR posted @ 2015年8月18日 21:54 in 题解 , 489 阅读

Day10考的时候T1很快就水完了,T2早早弃疗,反正有70分暴力,T3怎么看怎么像SB题,于是考前1h就检查完不管了

不过有人质疑了T3题意,我才发现我TM也看错了。

题解:

所以做这道题只有半个+h,很明显看得出这是树状数组搞一搞就可以了,但是卧榻马并不会这种东西= =,一般都是用线段树。于是本来还打算临时推一下怎么搞这个东西。然后发现其实线段树就可以搞了。首先建一棵有2k个节点的线段树,每次染色就是直接区间加值,每次询问节点t就从[t,t]这个节点一直往上走,如果当前节点是父亲的左儿子就把当前的节点的区间的右端点权值加入答案,正确性感觉还是比较显然的。于是考场上面还算是搞出来了,事后想想这性质还是蛮屌的= =

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
#define N 1000050
int t[N*3],ad[N*3],M,n,m;char b[20];
inline int Read()
 {
	 int x=0;char y;
	 do y=getchar(); while (y<'0'||y>'9');
	 do x=x*10+y-'0',y=getchar(); while (y>='0'&&y<='9');
	 return x;
 }
inline void adj(int x,int y,int z)
 {int j=z << 1;if (!ad[z]) return;t[z]+=ad[z];if (x!=y) ad[j]+=ad[z],ad[j+1]+=ad[z];ad[z]=0;}
void Modify(int x,int y,int z,int o,int p)
 {
	 int i=x + y >> 1,j=z << 1;
	 adj(x,y,z);
	 if (x==o&&y==p) {ad[z]++;return;}
	 if (o<=i) Modify(x,i,j,o,min(i,p));
	 if (p>i) Modify(i+1,y,j+1,max(o,i+1),p);
	 if (p==y) t[z]++;
 }
int Query(int x,int y,int z,int o)
 {
	 int i=x + y >> 1,j=z << 1;
	 adj(x,y,z);
	 if (x==y) return t[z];
	 if (o<=i) return t[z]+Query(x,i,j,o);else return Query(i+1,y,j+1,o);
 }
int main()
 {
	 freopen("array.in","r",stdin);freopen("array.out","w",stdout);
	 n=Read();m=Read();
	 M=1 << 20;
	 while (m--)
	  {
		  int k,l;
		  scanf("%s",b);
		  if (b[0]=='C') k=Read(),l=Read(),Modify(1,M,1,k,l);else
			 printf("%d\n",Query(1,M,1,Read()));
	  }
	 return 0;
 }

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter