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 }
T1

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);
    }
}
T2

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 }
乱搞

 

posted on 2021-08-11 20:35  JYFHYX  阅读(36)  评论(0编辑  收藏  举报