题面:https://www.cnblogs.com/Juve/articles/11791219.html
上来先看T1,发现和之前做过的treap一样,是线段树维护单调栈,然后打了一个小时,然后它挂了
于是看后面的题,然后T2:woc它说的是什么?怎么这么多变量?貌似k=2可以大力分类讨论?
写了半个小时,发现恶心至极,然后puts("-1")就跑了
T3好像有暴力?打了个搜索,一遍过样例,应该有40分了吧,在加上T1暴力就60分了
突然发现T1可以分块直接艹过,果断分块,然后过样例,对拍出锅,
对拍发现了4出错误,然后改完了发现我的分块会被卡成n方?
如果是一个单增的序列,然后他要修改一个特别靠前的位置,我就成n2了,但是这种数据倒也跑的挺快,只是对拍不过
最后半个小时,检查了一下文件名,然后T3本着骗分的原则我按a+b排序从大到小输出
然后改了改T1,发现它过拍了,然后就这样了,一直到考试结束,感觉T1可能会被卡
期望得分:80+10+30=120
实际得分:100+10+100=210!!??
T3不是正解居然A了。。。我rp估计要掉光了,然后T1没有被卡??!!
其实$nlog^2n$和$n\sqrt{n}$复杂度差不多,卡我时间还是挺难的,虽说正解只有一个log,但是常数没有分块优秀
T1:
说是分块其实就是优化的暴力
预处理原序列的前缀答案,前缀最大值,块内最值,
那么每次修改对于前面的答案没有影响,直接接过来,然后在本块中跑暴力,把修改位置所在块的贡献加上,同时记录到当前块的最大值
然后扫后面的块,如果块内最大值比当前最大值小,那么这个块没有用,反之就暴力更新块内的答案
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 #define re register 7 using namespace std; 8 const int MAXN=1e5+5; 9 inline int read(){ 10 re int x=0,f=1;re char ch=getchar(); 11 while(ch<'0'||ch>'9'){ 12 if(ch=='-') f=-1; 13 ch=getchar(); 14 } 15 while(ch>='0'&&ch<='9'){ 16 x=(x<<3)+(x<<1)+ch-'0'; 17 ch=getchar(); 18 } 19 return x*f; 20 } 21 int n,m,a[MAXN],pos[MAXN],b[MAXN],d[MAXN],maxx=0; 22 int blo,bel[MAXN],l[MAXN],r[MAXN],tot,mx[MAXN],len[MAXN],fmx[MAXN],smx[MAXN],p[MAXN]; 23 signed main(){ 24 freopen("TaoPApp.in","r",stdin); 25 freopen("TaoPApp.out","w",stdout); 26 n=read(),m=read(); 27 blo=sqrt(n)+1; 28 tot=n/blo; 29 if(n%blo) ++tot; 30 for(re int i=1;i<=n;++i){ 31 a[i]=read(); 32 bel[i]=(i-1)/blo+1; 33 } 34 for(re int i=1;i<=tot;++i){ 35 l[i]=r[i-1]+1; 36 r[i]=i*blo; 37 } 38 r[tot]=min(r[tot],n); 39 for(re int i=1;i<=tot;++i){ 40 for(re int j=l[i];j<=r[i];++j){ 41 if(fmx[i]<=a[j]){ 42 fmx[i]=a[j]; 43 p[i]=j; 44 } 45 } 46 for(re int j=l[i];j<=r[i];++j){ 47 if(j!=p[i]&&smx[i]<=a[j]){ 48 smx[i]=a[j]; 49 } 50 } 51 } 52 for(re int i=1;i<=n;++i){ 53 mx[i]=max(mx[i-1],a[i]); 54 len[i]=len[i-1]; 55 if(maxx<a[i]){ 56 maxx=a[i]; 57 ++len[i]; 58 } 59 } 60 for(re int i=1;i<=m;++i){ 61 pos[i]=read(),b[i]=read(); 62 re int tmp=a[pos[i]]; 63 a[pos[i]]=b[i]; 64 re int c=bel[pos[i]];//当前块 65 re int res=len[l[c]-1];//当前块前的答案 66 re int zd=mx[l[c]-1];//上一个块前的最大值 67 for(re int j=l[c];j<=r[c];++j){ 68 if(zd<a[j]){ 69 zd=a[j]; 70 ++res; 71 } 72 } 73 if(pos[i]!=p[c]){ 74 for(re int j=c+1;j<=tot;++j){ 75 if(mx[r[j]]<=zd) continue; 76 for(re int k=l[j];k<=r[j];++k){ 77 //++tot; 78 if(zd<a[k]){ 79 zd=a[k]; 80 ++res; 81 } 82 } 83 res+=len[n]-len[r[j]]; 84 break; 85 } 86 printf("%d\n",res); 87 a[pos[i]]=tmp; 88 }else{ 89 re int tmpp=max(zd,smx[c]); 90 tmpp=max(tmpp,b[i]); 91 for(re int j=c+1;j<=tot;++j){ 92 if(fmx[j]<=tmpp) continue; 93 for(re int k=l[j];k<=r[j];++k){ 94 if(tmpp<a[k]){ 95 tmpp=a[k]; 96 ++res; 97 } 98 } 99 } 100 printf("%d\n",res); 101 a[pos[i]]=tmp; 102 } 103 } 104 return 0; 105 } 106 /* 107 5 3 108 1 2 3 4 4 109 1 5 110 5 5 111 2 3 112 */