T1Dove打扑克
size最多有根号种,所以可以把当前所有的size存起来,询问只遍历这里面的就OK了
1 #include<bits/stdc++.h> 2 #define int long long 3 using namespace std; 4 inline int read() 5 { 6 int x=0,f=1; char ch=getchar(); 7 while(ch<'0'||ch>'9'){if(ch=='-') f=-1; ch=getchar();} 8 while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} 9 return x*f; 10 } 11 const int maxn=5e5+5; 12 int n,m,opt; 13 int fa[maxn],size[maxn],cnt[maxn],sum,maxx=1; 14 bool vis[maxn]; 15 int tp[maxn]; 16 int tong[maxn]; 17 struct szsz{ 18 int c[maxn]; 19 inline int lowbit(int x){return x&(-x);} 20 inline void update(int x,int val){while(x<=n){c[x]+=val;x+=lowbit(x);}} 21 inline int query(int x){int res=0;while(x){res+=c[x];x-=lowbit(x);}return res;} 22 }s; 23 inline int getfa(int x){if(fa[x]==x) return x;return fa[x]=getfa(fa[x]);} 24 inline void merge(int x,int y) 25 { 26 int xx=getfa(x),yy=getfa(y); 27 fa[yy]=xx; if(xx==yy) return ; 28 vis[yy]=0;cnt[size[yy]]--;sum--;maxx=max(maxx,size[xx]+size[yy]); 29 cnt[size[xx]]--;cnt[size[xx]+size[yy]]++; 30 if(!tp[size[xx]+size[yy]]) 31 tong[++tong[0]]=size[xx]+size[yy],tp[size[xx]+size[yy]]=1; 32 s.update(size[xx],-1);s.update(size[yy],-1); 33 s.update(size[xx]+size[yy],1); 34 size[xx]+=size[yy];size[yy]=0; 35 } 36 signed main() 37 { 38 //freopen("a.in","r",stdin); 39 //freopen("out","w",stdout); 40 memset(fa,0,sizeof(fa));tong[++tong[0]]=1; 41 sum=n=read();m=read();cnt[1]=n; for(int i=1;i<=n;i++) 42 {fa[i]=i;size[i]=1;s.update(size[i],1);vis[i]=1;} 43 while(m--) 44 { 45 opt=read(); 46 if(opt==1) 47 { 48 int x=read(),y=read(); 49 merge(x,y); 50 } 51 else 52 { 53 int g=read(),ans=0; 54 if(g) 55 { 56 if(g>=n){ puts("0");continue;} 57 for(int i=1;i<=tong[0];i++) 58 { 59 int x=tong[i]; 60 if(!cnt[x]) continue; 61 if(x<g) continue; 62 ans+=cnt[x]*s.query(x-g); 63 } 64 } 65 else ans=(sum-1)*(sum)/2; 66 printf("%lld\n",ans); 67 } 68 } 69 }
T2Cicada 与排序
考场上根本看不懂,但是考完之后稍微分析一下就可以发现,我们可以模拟归并排序的过程
找出每种情况出现的概率,进行dp就好了
我们定义g[ i ][ j ]表示归并排序的两个指针同时指到i和j的概率,这个可以分类讨论进行操作
再定义f[ i ][ j ][ k ]表示在归并排序的第i层里,i在j的概率是多少,这个可以继续分类讨论并用g更新
分类讨论是比较容易的,这里就不多说了,无非就是5种情况,左区间完了,右区间完了,左边的数大于右边
左边的数小于右边,左右两边的数相等
最后统计答案就好了
#include<bits/stdc++.h> #define int long long using namespace std; inline int read() { int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-') f=-1; ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} return x*f; } const int mod=998244353; const int inv2=499122177; int dp[501][501][501],g[501][501],n; int a[501]; void msort(int x,int l,int r) { if(l==r){dp[x][l][l]=1;return;} int mid=(l+r)>>1; msort(x+1,l,mid); msort(x+1,mid+1,r); memset(g,0,sizeof(g)); g[0][0]=1; for(int i=0;i<=mid-l+1;i++) for(int j=0;j<=r-mid;j++) { if(i==mid-l+1)g[i][j+1]=(g[i][j+1]+g[i][j])%mod; else if(j==r-mid)g[i+1][j]=(g[i+1][j]+g[i][j])%mod; else if(a[i+l]<a[j+mid+1])g[i+1][j]=(g[i+1][j]+g[i][j])%mod; else if(a[i+l]>a[j+mid+1])g[i][j+1]=(g[i][j+1]+g[i][j])%mod; else { g[i+1][j]=(g[i+1][j]+g[i][j]*inv2%mod)%mod; g[i][j+1]=(g[i][j+1]+g[i][j]*inv2%mod)%mod; } } for(int i=l;i<=r;i++) for(int j=0;j<=mid-l+1;j++) for(int k=0;k<=r-mid;k++) { if(j==mid-l+1&&k==r-mid)continue; if(j==mid-l+1)dp[x][i][j+k+l]=(dp[x][i][j+k+l]+dp[x+1][i][k+mid+1]*g[j][k]%mod)%mod; else if(k==r-mid)dp[x][i][j+k+l]=(dp[x][i][j+k+l]+dp[x+1][i][j+l]*g[j][k]%mod)%mod; else if(a[j+l]<a[k+mid+1])dp[x][i][j+k+l]=(dp[x][i][j+k+l]+dp[x+1][i][j+l]*g[j][k]%mod)%mod; else if(a[j+l]>a[k+mid+1])dp[x][i][j+k+l]=(dp[x][i][j+k+l]+dp[x+1][i][k+mid+1]*g[j][k]%mod)%mod; else { dp[x][i][j+k+l]=(dp[x][i][j+k+l]+dp[x+1][i][k+mid+1]*g[j][k]%mod*inv2%mod)%mod; dp[x][i][j+k+l]=(dp[x][i][j+k+l]+dp[x+1][i][j+l]*g[j][k]%mod*inv2%mod)%mod; } } sort(a+l,a+r+1); } signed main() { n=read();for(int i=1;i<=n;i++) a[i]=read(); msort(1,1,n); for(int i=1;i<=n;i++) { int ans=0; for(int j=1;j<=n;j++) (ans+=dp[1][i][j]*j%mod)%=mod; printf("%lld ",ans); } }
T3Cicada 拿衣服
呃呃。。。n^2暴力可拿64,再加上一点大胆的乱搞,可以水过
我们假设题的数据是随机的,嗯。。。。。。。
我们再假设它每个数字为左端点最长的区间不超过100,嗯。。。。。。。
然后就可以水过了;
正解嘛。。。那么多人都写了,可以去看看其他人的/doge
1 #include<bits/stdc++.h> 2 #define lid id<<1 3 #define rid id<<1|1 4 using namespace std; 5 inline int read() 6 { 7 int x=0,f=1; char ch=getchar(); 8 while(ch<'0'||ch>'9'){if(ch=='-') f=-1; ch=getchar();} 9 while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} 10 return x*f; 11 } 12 const int maxn=1e6+1; 13 int n,k,a[maxn],h[maxn],yu[maxn]; 14 struct tree{ 15 int l,r,mx,lazy; 16 }tr[maxn*4]; 17 void pushup(int id) {tr[id].mx=max(tr[lid].mx,tr[rid].mx);} 18 void pushdown(int id) 19 { 20 if(!tr[id].lazy) return ; 21 tr[lid].lazy=max(tr[id].lazy,tr[lid].lazy); 22 tr[rid].lazy=max(tr[id].lazy,tr[rid].lazy); 23 tr[lid].mx=max(tr[id].lazy,tr[lid].mx); 24 tr[rid].mx=max(tr[id].lazy,tr[rid].mx); 25 tr[id].lazy=0; 26 } 27 void build(int id,int l,int r) 28 { 29 tr[id].l=l;tr[id].r=r; 30 if(l==r)return ; 31 int mid=l+r>>1;build(lid,l,mid); 32 build(rid,mid+1,r); 33 } 34 void update(int id,int l,int r,int val) 35 { 36 if(tr[id].l>=l&&tr[id].r<=r) 37 { 38 tr[id].lazy=max(tr[id].lazy,val); 39 tr[id].mx=max(tr[id].lazy,tr[id].mx); 40 return ; 41 }pushdown(id);int mid=tr[id].r+tr[id].l>>1; 42 if(l<=mid) update(lid,l,r,val); 43 if(r>mid) update(rid,l,r,val); 44 pushup(id); 45 } 46 inline int query(int id,int pos) 47 { 48 if(tr[id].l==tr[id].r)return tr[id].mx; 49 int mid=tr[id].l+tr[id].r>>1; 50 pushdown(id); 51 if(pos<=mid) return query(lid,pos); 52 else return query(rid,pos); 53 } 54 int main() 55 { 56 n=read();k=read(); for(int i=1;i<=n;i++) 57 { a[i]=read();h[i]^=a[i];}build(1,1,n); 58 if(n<=30000) 59 { 60 for(int i=1;i<=n;i++) 61 { 62 yu[i]=a[i];int maxx=a[i],minn=a[i],r=-1; 63 for(int j=i+1;j<=n;j++) 64 { 65 maxx=max(a[j],maxx);minn=min(a[j],minn); 66 h[i]=h[i]|a[j];yu[i]=yu[i]&a[j]; 67 if(minn+h[i]-maxx-yu[i]>=k) r=j; 68 } 69 if(r!=-1) update(1,i,r,r-i+1); 70 } 71 } 72 else 73 { 74 for(int i=1;i<=n;i++) 75 { 76 yu[i]=a[i];int maxx=a[i],minn=a[i],r=-1; 77 for(int j=i+1;j<=n;j++) 78 { 79 maxx=max(a[j],maxx);minn=min(a[j],minn); 80 h[i]=h[i]|a[j];yu[i]=yu[i]&a[j]; 81 if(minn+h[i]-maxx-yu[i]>=k) r=j; 82 else if(j-i+1>100) break; 83 } 84 if(r!=-1) update(1,i,r,r-i+1); 85 } 86 } 87 for(int i=1;i<=n;i++) 88 { 89 int ans=query(1,i); 90 if(!ans){printf("-1 ");} 91 else{printf("%d ",ans);} 92 } 93 cout<<endl; 94 }