這一輪是要鬧哪樣啊???前十都死活進不去???c++
能不能不要到聯賽前忽然連續掉鏈子啊!!!數組
總算可貴的切掉了T1。而後又一次把T2和T3的難度估反了ide
結果給T2剩下了30分鐘,想到正解來不及打了。函數
而後T3沒有亂搞丟了不少分。(循環不用跑滿,上限能到80。。。考後還有AC的)優化
聯賽題目的難度基本是升序。。。ui
學會亂搞,要有信仰。。。spa
T1必須佔用更少的時間,想到並證實正確以後就快速打出來code
T1:Dave打撲克blog
能夠證實,數量本質不一樣的堆數至多爲根號個。排序
因此並查集維護,用unordered_set迭代器遍歷,用樹狀數組計數詢問便可。
1 #include<cstdio> 2 #include<unordered_set> 3 using namespace std; 4 unordered_set<int>S; 5 int n,m,t[200005],buc[200005],siz[100005],f[100005]; 6 void add(int p,int w){for(;p<=200000;p+=p&-p)t[p]+=w;} 7 int ask(int p,int a=0){for(;p;p^=p&-p)a+=t[p];return a;} 8 int find(int p){return f[p]==p?p:f[p]=find(f[p]);} 9 int main(){//freopen("cards105.in","r",stdin);freopen("my.out","w",stdout); 10 scanf("%d%d",&n,&m); 11 buc[1]=n;S.insert(1);add(1,n); 12 for(int i=1;i<=n;++i)f[i]=i,siz[i]=1; 13 for(int i=1,opt,x,y;i<=m;++i){ 14 scanf("%d",&opt); 15 if(opt==1){ 16 scanf("%d%d",&x,&y); 17 x=find(x);y=find(y); 18 if(x==y)continue; 19 add(siz[x],-1);add(siz[y],-1);add(siz[x]+siz[y],1); 20 buc[siz[x]]--;buc[siz[y]]--;buc[siz[x]+siz[y]]++; 21 if(!buc[siz[x]])S.erase(siz[x]); 22 if(!buc[siz[y]])S.erase(siz[y]); 23 if(buc[siz[x]+siz[y]]==1)S.insert(siz[x]+siz[y]); 24 siz[y]+=siz[x];f[x]=y;n--; 25 }else{ 26 scanf("%d",&x);long long ans=n*(n-1ll)>>1; 27 if(!x){printf("%lld\n",ans);continue;} 28 unordered_set<int>::iterator it=S.begin(); 29 while(it!=S.end()){ 30 y=*it; 31 ans-=1ll*buc[y]*(ask(y+x-1)-ask(y)); 32 ans-=1ll*buc[y]*(buc[y]-1)>>1; 33 it++; 34 }printf("%lld\n",ans); 35 } 36 } 37 }
T2:Cicada與排序
歸併排序每一個數也就會遞歸下去log層。
因此咱們不斷考慮每一個數在參與一次歸併後的相對排名就行了。
固然數字不同的最後排名確定好說,如今只考慮每一個數在全部與它相同的數裏的相對排名(如下簡稱「位置」)
設rk[i][j]表示最開始位置在i的數在歸併後所在的位置。
而後咱們考慮如何轉移,咱們須要的其實就是一個「兩個數組歸併,其中第一個數組的第p位在歸併後的數組排第q位的機率」
這個能夠dp求出。dp[i][j][0/1]表示歸併排序時第一個數組彈掉了i個,第二個數組彈掉了j個,最後一次彈的來自於第一組仍是第二組。
這樣的話最後彈掉的元素就是排名第i+j的元素了,而在歸併以前的排名就是i或j(取決於來源)
具體的轉移其實就是考慮兩個數組是否是已經被彈乾淨了,彈乾淨了一個那就只能彈另外一個,不然就隨機彈一個
轉移比較簡單,本身想比較好(這個已經比題解的那個簡單不少了)實在不行再頹碼
這個dp數組固然與兩個原數組的長度有關,因此要放在merge_sort裏面處理,而非全局預處理(這不是題解思路)
而後rk也就能夠轉移了,枚舉歸併先後的排名便可。
不要memset。跑的很快的。
複雜度的證實可能要等到學積分?極端數據是全部數都相同。
並非積分,是主定理啦!
這道題知足第三條。$f(n)=\Omega (n^3)$,
這樣的話$\epsilon =2>0$
此時c取$\frac{1}{4}$時知足後者條件即
$2f(\frac{n}{2})<=\frac{1}{4}f(n)$,其中$a=b=2$
因此總複雜度$O(n^3)$
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define mod 998244353 4 #define inv 499122177 5 #define int long long 6 vector<int>lv[1005],rv[1005]; 7 int n,x[505],rk[505][505],Rcnt[1005],Lcnt[1005],tem[505],dp[505][505][2]; 8 void merge_sort(int l,int r){ 9 if(l==r)return; int M=l+r>>1; 10 merge_sort(l,M); merge_sort(M+1,r); 11 for(int i=l;i<=M;++i)Lcnt[x[i]]++,lv[x[i]].push_back(i); 12 for(int i=M+1;i<=r;++i)Rcnt[x[i]]++,rv[x[i]].push_back(i); 13 for(int i=1;i<=1000;++i){ 14 for(int L=0;L<=Lcnt[i];++L)for(int R=0;R<=Rcnt[i];++R)dp[L][R][0]=dp[L][R][1]=0; 15 dp[0][0][0]=1; 16 for(int L=0;L<=Lcnt[i];++L)for(int R=0;R<=Rcnt[i];++R) 17 if(L!=Lcnt[i]&&R!=Rcnt[i]) 18 dp[L+1][R][0]=(dp[L+1][R][0]+(dp[L][R][0]+dp[L][R][1])*inv)%mod, 19 dp[L][R+1][1]=(dp[L][R+1][1]+(dp[L][R][0]+dp[L][R][1])*inv)%mod; 20 else if(L!=Lcnt[i])dp[L+1][R][0]=(dp[L+1][R][0]+dp[L][R][0]+dp[L][R][1])%mod; 21 else if(R!=Rcnt[i])dp[L][R+1][1]=(dp[L][R+1][1]+dp[L][R][0]+dp[L][R][1])%mod; 22 for(int j=0;j<Lcnt[i];++j){ 23 for(int k=1;k<=Lcnt[i];++k)for(int rp=0;rp<=Rcnt[i];++rp) 24 tem[k+rp]=(tem[k+rp]+rk[lv[i][j]][k]*dp[k][rp][0])%mod; 25 for(int nrk=1;nrk<=Lcnt[i]+Rcnt[i];++nrk)rk[lv[i][j]][nrk]=tem[nrk],tem[nrk]=0; 26 } 27 for(int j=0;j<Rcnt[i];++j){ 28 for(int k=1;k<=Rcnt[i];++k)for(int lp=0;lp<=Lcnt[i];++lp) 29 tem[k+lp]=(tem[k+lp]+rk[rv[i][j]][k]*dp[lp][k][1])%mod; 30 for(int nrk=1;nrk<=Lcnt[i]+Rcnt[i];++nrk)rk[rv[i][j]][nrk]=tem[nrk],tem[nrk]=0; 31 } 32 lv[i].clear();rv[i].clear();Lcnt[i]=Rcnt[i]=0; 33 } 34 } 35 main(){//freopen("sort103.in","r",stdin); 36 scanf("%lld",&n); 37 for(int i=1;i<=n;++i)scanf("%lld",&x[i]); 38 for(int i=1;i<=n;++i)rk[i][1]=1; 39 merge_sort(1,n); 40 for(int i=1;i<=n;++i)Lcnt[x[i]]++; 41 for(int i=1;i<=1000;++i)Lcnt[i]+=Lcnt[i-1]; 42 for(int i=1;i<=n;++i){ 43 int ans=0; 44 for(int j=1;j<=Lcnt[x[i]]-Lcnt[x[i]-1];++j)ans=(ans+1ll*rk[i][j]*j)%mod;//,printf("%lld %lld\n",j,rk[i][j]); 45 printf("%lld ",ans+Lcnt[x[i]-1]); 46 }puts(""); 47 }
T3:Cicada拿衣服
英文題目名爲何叫naive??拿(na)衣(i)服(ve)???
看到這個題目名我還覺得這道題真的很naive
其實只是比較好打,可是思路不是很好想
首先你須要打一個暴力,須要一個ST表來O(1)查詢區間的那四個函數。
發現Dybala的ST表仍是O(log)的。。。奉勸各位好好學學ST表。。。
highbit操做是要預處理的!!!不要現算!!!
而後最粗暴的就是枚舉左右端點,check它的excited值,若是合法就區間取max。我是用線段樹維護的。
到這裏爲止若是你不亂搞你能有36分。
而後正解的80%就已經打完了。
首先咱們固定右端點,不斷左移左端點。
對於OR,最多隻會變化log次,即每一位從0變成1。
對於AND,最多也只會變化log次,每一位從1到0。
因此其實OR-AND只會變化2log次。
那麼問題就是MIN-MAX了。MIN愈來愈小MAX愈來愈大因此MIN-MAX會愈來愈小。
因此在由OR-AND分割出的2log段裏,每一段內部的excited值都知足單調性。
因此咱們只要考慮在每一段裏找到最靠左的excited值的合法位置,而後就線段樹區間賦取max就行了。
而後怎麼找到這2log個段呢?
用鏈表記錄下每一個段的右端點就行了,而後跳鏈表就能夠。
由於右端點右移的時候,鏈表內部只會合併段而不會新增段,因此是能夠用鏈表的。
因此代碼其實只是多了一個鏈表,而後爆掃改爲跳鏈表而已。
複雜度是$O(nlogn)$
這題數據很難造,因此亂搞可過。然而打正解須要優化常數否則容易T92什麼的。。。
記得及時跳出否則仍是$nlog^2$。。。我就是hanpi
1 #include<bits/stdc++.h> 2 using namespace std; 3 int mx[20][1000005],mn[20][1000005],Or[20][1000005],And[20][1000005]; 4 int ans[1000005],n,x[1000005],hi[1000005],k,t[4000005],cl[4000005],cr[4000005]; 5 int lst[1000005],nxt[1000005]; 6 void del(int p){lst[nxt[p]]=lst[p];nxt[lst[p]]=nxt[p];} 7 const int N=1e6+10; 8 const int Ls=1<<23|1; 9 char buffer[Ls],*Ss,*Ts; 10 #define getchar() ((Ss==Ts&&(Ts=(Ss=buffer)+fread(buffer,1,Ls,stdin),Ss==Ts))?EOF:*Ss++) 11 int read(register int p=0,register char ch=getchar()){ 12 while(ch<'0'||ch>'9')ch=getchar(); 13 while(ch>='0'&&ch<='9')p=(p<<3)+(p<<1)+ch-'0',ch=getchar(); 14 return p; 15 } 16 #define Max(a,b) ((a)>(b)?(a):(b)) 17 #define Min(a,b) ((a)<(b)?(a):(b)) 18 int _max(int l,int r){ 19 int x=hi[r-l+1]; 20 return Max(mx[x][l],mx[x][r-(1<<x)+1]); 21 } 22 int _min(int l,int r){ 23 int x=hi[r-l+1]; 24 return Min(mn[x][l],mn[x][r-(1<<x)+1]); 25 } 26 int _or(int l,int r){ 27 int x=hi[r-l+1]; 28 return Or[x][l]|Or[x][r-(1<<x)+1]; 29 } 30 int _and(int l,int r){ 31 int x=hi[r-l+1]; 32 return And[x][l]&And[x][r-(1<<x)+1]; 33 } 34 int excited(int l,int r){ 35 return _or(l,r)-_max(l,r)+_min(l,r)-_and(l,r); 36 } 37 void build(int p,int l,int r){ 38 cl[p]=l;cr[p]=r;t[p]=-1; 39 if(l==r)return; 40 build(p<<1,l,l+r>>1); 41 build(p<<1|1,(l+r>>1)+1,r); 42 } 43 void modify(int p,int l,int r,int w){ 44 if(l<=cl[p]&&cr[p]<=r)return t[p]=Max(t[p],w),(void)0; 45 if(l<=cr[p<<1]) modify(p<<1,l,r,w); 46 if(r>cr[p<<1]) modify(p<<1|1,l,r,w); 47 } 48 void dfs(int p,int w){ 49 w=Max(w,t[p]); 50 if(cl[p]==cr[p])return printf("%d ",w),(void)0; 51 dfs(p<<1,w); dfs(p<<1|1,w); 52 } 53 int chk(int l,int r,int R){ 54 while(l<r-1)if(excited(l+r>>1,R)>=k)r=l+r>>1;else l=(l+r>>1)+1; 55 if(excited(l,R)>=k)return l;return r; 56 } 57 int main(){//freopen("naive105.in","r",stdin);freopen("my.out","w",stdout); 58 scanf("%d%d",&n,&k);build(1,1,n); 59 for(int i=1;i<=n;++i)x[i]=read(),lst[i]=i-1,nxt[i]=i+1; 60 nxt[0]=1; 61 for(int i=1;i<=n;++i) mx[0][i]=mn[0][i]=Or[0][i]=And[0][i]=x[i]; 62 for(int j=1;j<20;++j)for(int i=1;i+(1<<j)-1<=n;++i) 63 mx[j][i]=Max(mx[j-1][i],mx[j-1][i+(1<<j-1)]), 64 mn[j][i]=Min(mn[j-1][i],mn[j-1][i+(1<<j-1)]), 65 Or[j][i]=Or[j-1][i]|Or[j-1][i+(1<<j-1)], 66 And[j][i]=And[j-1][i]&And[j-1][i+(1<<j-1)]; 67 for(int j=0;j<20;++j)for(int i=1<<j;i<1<<j+1&&i<=n;++i)hi[i]=j; 68 for(int r=1;r<=n;++r){ 69 for(int i=lst[r];i;i=lst[i])if(_or(nxt[i],r)==_or(i,r)&&_and(nxt[i],r)==_and(i,r))del(i); 70 for(int i=nxt[0],p;i<=r;i=nxt[i])if(excited(i,r)>=k){p=chk(lst[i]+1,i,r),modify(1,p,r,r-p+1);break;} 71 } 72 dfs(1,-1);puts(""); 73 }