題面:https://www.cnblogs.com/Juve/articles/11791219.htmlhtml
上來先看T1,發現和以前作過的treap同樣,是線段樹維護單調棧,而後打了一個小時,而後它掛了node
因而看後面的題,而後T2:woc它說的是什麼?怎麼這麼多變量?貌似k=2能夠大力分類討論?ios
寫了半個小時,發現噁心至極,而後puts("-1")就跑了app
T3好像有暴力?打了個搜索,一遍過樣例,應該有40分了吧,在加上T1暴力就60分了ide
忽然發現T1能夠分塊直接艹過,果斷分塊,而後過樣例,對拍出鍋,優化
對拍發現了4出錯誤,而後改完了發現個人分塊會被卡成n方?spa
若是是一個單增的序列,而後他要修改一個特別靠前的位置,我就成n2了,可是這種數據倒也跑的挺快,只是對拍不過code
最後半個小時,檢查了一下文件名,而後T3本着騙分的原則我按a+b排序從大到小輸出orm
而後改了改T1,發現它過拍了,而後就這樣了,一直到考試結束,感受T1可能會被卡htm
指望得分: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 }