题面: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 */
T2:
贪心+模拟

1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 #include<algorithm>
5 #include<set>
6 #define int long long
7 using namespace std;
8 const int MAXN=5e4+5;
9 inline int read(){
10 int x=0,f=1;char ch=getchar();
11 while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
12 while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
13 return x*f;
14 }
15 int k,c[MAXN],d[MAXN],m[MAXN],p[MAXN],e[MAXN],r[MAXN],E[MAXN],cst,tot=0,ans=0;
16 struct node{
17 int num,cost;
18 friend bool operator < (node a,node b){
19 return a.cost<b.cost;
20 }
21 };
22 multiset<node>s1,s2;
23 signed main(){
24 freopen("happy.in","r",stdin);
25 freopen("happy.out","w",stdout);
26 k=read();
27 for(int i=1;i<=k;++i) c[i]=read(),d[i]=read(),m[i]=read(),p[i]=read();
28 for(int i=1;i<k;++i) e[i]=read(),r[i]=read(),E[i]=read();
29 cst=c[1];
30 for(int i=1;i<=k;++i){
31 if(p[i]) s1.insert((node){p[i],m[i]+cst});
32 tot+=p[i];
33 while(d[i]){
34 if(s1.empty()){
35 puts("-1");
36 return 0;
37 }
38 node x=*s1.begin();
39 int num=min(d[i],x.num);
40 s1.erase(s1.begin());
41 ans+=x.cost*num;
42 x.num-=num,tot-=num,d[i]-=num;
43 if(x.num) s1.insert(x);
44 }
45 if(i!=k){
46 cst=min(cst+r[i],c[i+1]);
47 while(tot>e[i]){
48 node x=*--s1.end();
49 int num=min(tot-e[i],x.num);
50 s1.erase(--s1.end());
51 tot-=num,x.num-=num;
52 if(x.num) s1.insert(x);
53 }
54 for(multiset<node>::iterator it=s1.begin();it!=s1.end();++it){
55 s2.insert((node){(*it).num,(*it).cost+E[i]});
56 }
57 swap(s1,s2),s2.clear();
58 }
59 }
60 printf("%lld\n",ans);
61 return 0;
62 }
T3:
按a排序,保留最大的A,然后在剩下的里面两两分组,组内取b较大的

1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 #include<algorithm>
5 #define int long long
6 using namespace std;
7 const int MAXN=4e5+5;
8 int n;
9 struct node{
10 int a,b,id;
11 friend bool operator < (node aa,node bb){
12 return aa.a==bb.a?aa.b>bb.b:aa.a>bb.a;
13 }
14 }p[MAXN];
15 signed main(){
16 freopen("grandmaster.in","r",stdin);
17 freopen("grandmaster.out","w",stdout);
18 scanf("%lld",&n);
19 for(int i=1;i<=2*n+1;++i){
20 scanf("%lld%lld",&p[i].a,&p[i].b);
21 p[i].id=i;
22 }
23 sort(p+1,p+2*n+1+1);
24 printf("%lld\n",p[1].id);
25 for(int i=2;i<=2*n+1;i+=2){
26 if(p[i].b>p[i+1].b){
27 printf("%lld\n",p[i].id);
28 }
29 else printf("%lld\n",p[i+1].id);
30 }
31 return 0;
32 }
