zoukankan      html  css  js  c++  java
  • [考试反思]0604四校联考第一轮day2:黑马

    第一轮结束了。总榜排名$rk8$在本校中$rk4$

    考虑上$csp-s$的分数的话,妥妥退役。

    在我前面的我翻不动,在我后面的也能随便把我翻了,结果就没什么好说的。

    最近状态还是不好。抓紧调整吧,没有时间了。

    越发浓郁的文化课味道

    今天的话,上来先看的$T2$,$52pts$貌似比较简单,思路大概知道,先放了。

    然后看的是$T1$发现就是一个简单的线段树优化$dp$,于是就开始写,没写多久写完了过样例。

    $T3$写的树套树,写了一大摊调了好半天。过样例了。这时候看起来还挺顺,这时候是$10:00$

    然后开始上对拍,拍$T1$不出错,很开心,自信估分$100$

    然后接着拍$T3$,然而最开始思路是假的,被对拍干掉了,$10:30$拍出错,然后想了半天怎么改(最开始一直以为只是写挂了

    没想出来,期望得分剩下$40$。后来教练突然删了一档部分分,期望只剩下$20$。

    然后十分愤怒,于是就拼命改,想正解,然后发现了问题再一顿猛改,过了对拍,这时候是$11:30$

    这时候已经考虑到了内存问题,对于$3 imes 10^5$的数据范围十分无奈。估分$20$(然而不知道是数据水还是常数小并没有$MLE$)

    最后剩下很少的时间给$T2$,把原有思路一顿写然后过了样例,很开心,本场估分$248$。

    然而$T1,2$各炸了一个细节,分别挂了$30,48$分。人都挂没了

    $T1$的对拍的数据生成写的不好,$Dyyb$大神的对拍一组数据就把我卡了我自己$AC$了$50000$组。自闭了。

    T1:旅游

    大意:数轴,$x$出发最终要走到$y$,每次最多从$p$跳到$p+z$,每跳一次花费$a$。有$n$个特殊点,跳到特殊点上会有$w_i$收益。最大化总收益。$n le 10^5,1 le x,y,z,a le 10^9$

    首先最简单的$O(n^2)dp$不用说。然后当然可以套用$O(1000n)$的乱搞。可以得到$90pts$的好成绩,要比写挂的正解舒服的多。(数据水死算了

    我们看一下转移式子,大概是$dp_i=max(dp_j+w_i + lceil frac{p_i-p_i}{z} ceil imes a)$

    把上取整拆开,发现$a$的系数只与$lfloor frac{p_i}{z} floor,lfloor frac{p_j}{z} floor,p_i mod z <? p_j mod z$

    对于最后一部分,如果小于的话那么要额外产生$a$代价。所以线段树下标按照$p_i mod z$查询的时候区间加就可以

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define ll long long
     4 unordered_map<int,int>M;
     5 const int S=4000007;const ll Inf=-1e18;
     6 int x,y,z,n,p[S],w[S],r[S],tl,tr; ll dp[S],mx[S],a,lz[S];
     7 bool cmp(int x,int y){return x%z<y%z||((x-y)%z==0&&x<y);}
     8 #define lc p<<1
     9 #define rc lc|1
    10 #define md (L+R>>1)
    11 void up(int p){mx[p]=max(mx[lc],mx[rc]);}
    12 void build(int p=1,int L=tl,int R=tr){
    13     if(L==R){mx[p]=r[L]==x?dp[tl]+x/z*a:Inf;return;}
    14     build(lc,L,md);build(rc,md+1,R); up(p);
    15 }
    16 void mdf(int x,ll v,int p=1,int L=tl,int R=tr){
    17     if(L==R){mx[p]=v;return;}
    18     if(x<=md)mdf(x,v,lc,L,md);else mdf(x,v,rc,md+1,R);
    19     up(p);
    20 }
    21 ll ask(int l,int r,int p=1,int L=tl,int R=tr){
    22     if(l<=L&&R<=r)return mx[p];
    23     return max(l<=md?ask(l,r,lc,L,md):Inf,r>md?ask(l,r,rc,md+1,R):Inf);
    24 }
    25 int main(){
    26     freopen("tourist.in","r",stdin);freopen("tourist.out","w",stdout);
    27     scanf("%d%d%d%lld%d",&x,&y,&z,&a,&n); tl=1,tr=n;
    28     for(int i=1;i<=n;++i)scanf("%d%d",&p[i],&w[i]),r[i]=p[i];
    29     if(p[n]!=y)p[++tr]=y,r[tr]=y; if(p[1]!=x)p[--tl]=x,r[tl]=x;
    30     sort(r+tl,r+1+tr,cmp);
    31     for(int i=tl;i<=tr;++i)M[r[i]]=i;
    32     dp[tl]=w[tl]; build();
    33     for(int i=tl+1;i<=tr;++i){
    34         int P=lower_bound(r+tl,r+tr+1,p[i]%z,cmp)-r;
    35         ll q=max(P==tl?Inf:ask(tl,P-1)-a,ask(P,tr))+w[i];
    36         dp[i]=-p[i]/z*a+q; mdf(M[p[i]],q);
    37     }printf("%lld",dp[tr]);
    38 }
    View Code

    T2:宝石

    大意:$n$石头,要求其中至少有$m$对颜色一样的(每一个石头只参与一次配对)。颜色有$d$种且石头有序。求所有情况中有多少种满足要求。$n,m le 10^9,d le 10^5$

    首先很明显的是,设$A$表示出现次数为奇数的颜色数,那么$n-2m ge A$。

    我们考虑指数型生成函数,首先出现次数不限奇偶的话生成函数就是$sumlimits_{i=0}^{infty} frac{x^i}{i!} = e^x$

    可以得到,出现次数为奇数的就是$F(x)=frac{e^x-e^{-x}}{2}$

    我们设$g_i$是至少有$i$种颜色出现了奇数次,那么$g_i=inom{d}{i} n! [x^n]e^{x(n-i)}(frac{e^x-e^{-x}}{2})^i$

    后面那玩意二项式定理展开并且把$e^x$都合并起来得到$n!inom{d}{i} frac{1}{2^i} [x^n] sumlimits_{j=0}^{i} inom{i}{j} (-1)^{i-j} e^{x(d+2j-2i)}$

    我们知道$[x^n]e^{xm}=frac{m^n}{n!}$。所以上面这个式子就会变成卷积形式。然后再二项式反演得到恰好形式就可以了。$O(dlog d)$

     1 #include<cstdio>
     2 #include<algorithm>
     3 using namespace std;
     4 const int S=1<<19,mod=998244353;
     5 int len=1,rev[S],fac[S],inv[S],n,m,d,A[S],f[S],ans;
     6 int qp(int b,int t,int a=1){for(;t;t>>=1,b=1ll*b*b%mod)if(t&1)a=1ll*a*b%mod;return a;}
     7 int mo(int x){return x>=mod?x-mod:x;}
     8 void NTT(int*a,int op=1){
     9     for(int i=0,x;i<len;++i)if(i<rev[i])swap(a[i],a[rev[i]]);
    10     for(int i=1;i<len;i<<=1)for(int j=0,w=qp(3,(mod-1)/2/i*op+mod-1);j<len;j+=i<<1)
    11         for(int k=j,t=1,x,y;k<j+i;++k,t=1ll*t*w%mod)
    12             x=a[k],y=1ll*t*a[k+i]%mod,a[k]=mo(x+y),a[k+i]=mo(x+mod-y);
    13     if(op==-1)for(int i=0,iv=qp(len,mod-2);i<len;++i)a[i]=1ll*a[i]*iv%mod;
    14 }
    15 int main(){
    16     freopen("jewel.in","r",stdin);freopen("jewel.out","w",stdout);
    17     scanf("%d%d%d",&d,&n,&m);
    18     for(int i=fac[0]=1;i<=d;++i)fac[i]=fac[i-1]*1ll*i%mod;
    19     A[d]=inv[d]=qp(fac[d],mod-2);
    20     for(int i=d-1;~i;--i)A[i]=inv[i]=inv[i+1]*(i+1ll)%mod;
    21     for(int i=0;i<=d;++i)f[i]=(i&1?mod-1ll:1ll)*qp(d-i-i+mod,n)%mod*A[i]%mod;
    22     while(len<=d+d)len<<=1;
    23     for(int i=0;i<len;++i)rev[i]=rev[i>>1]>>1|(i&1?len>>1:0);
    24     NTT(A);NTT(f);for(int i=0;i<len;++i)f[i]=1ll*f[i]*A[i]%mod;NTT(f,-1);
    25     for(int i=0;i<=d;++i)f[i]=1ll*f[i]*qp(2,mod-1-i)%mod*fac[i]%mod*fac[d]%mod*inv[d-i]%mod,A[i]=(i&1?mod-1ll:1ll)*inv[i]%mod;
    26     for(int i=d+1;i<len;++i)f[i]=A[i]=0;
    27     reverse(f,f+d+1);
    28     NTT(A);NTT(f);for(int i=0;i<len;++i)f[i]=1ll*f[i]*A[i]%mod;NTT(f,-1);
    29     reverse(f,f+d+1);
    30     for(int i=min(d,n-m-m);i>=0;--i)ans=(ans+f[i]*1ll*inv[i])%mod;
    31     printf("%d",ans);
    32 }
    View Code

    T3:线段

    大意:有$n+1$个点,$(i,i+1)$有边相连。支持:反转一条边的状态(连变成不连或者不连变成连),询问$x,y$两个点在多少个历史版本中是联通的。$n,q le 3 imes 10^5$

    题意也就是问有多少个历史状态满足区间$[x,y-1]$全都是$1$。

    每次修改只会使原来不联通现在联通的,或者反过来。

    假如修改的点是$x$,$x$所在的极长联通段是$[l,r]$,那么就会分别使得 询问左端点在$[l,x]$右端点在$[x,r]$的询问答案增加或减少当前时间。

    矩形加,单点询问。经典二维数点。直接树套树(内存有点危险但是莫名其妙过去了)。还是$CDQ$比较好。

    但是我都写了,那就不可能改了(还写的那么麻烦

     1 #include<cstdio>
     2 int max(int a,int b){return a>b?a:b;}
     3 const int S=300005,_=20000005;
     4 char s[S],o[9];int n,q,mx[S<<2],T=1,rt[S<<2],w[_],Lc[_],Rc[_],pc,lz[S<<2];
     5 #define lc p<<1
     6 #define rc lc|1
     7 #define md (L+R>>1)
     8 void build(int p=1,int L=1,int R=n){
     9     if(L==R){mx[p]=s[L]=='1'?0:S;return;}
    10     build(lc,L,md);build(rc,md+1,R); mx[p]=max(mx[lc],mx[rc]);
    11 }
    12 void down(int p){if(lz[p])lz[lc]=lz[p],lz[rc]=lz[p],mx[lc]=mx[p],mx[rc]=mx[p],lz[p]=0;}
    13 void up(int p){mx[p]=max(mx[lc],mx[rc]);}
    14 void segset(int l,int r,int p=1,int L=1,int R=n){
    15     if(l<=L&&R<=r){lz[p]=mx[p]=T;return;}
    16     down(p);if(l<=md)segset(l,r,lc,L,md);if(r>md)segset(l,r,rc,md+1,R); up(p);
    17 }
    18 int Max(int l,int r,int p=1,int L=1,int R=n){
    19     if(l<=L&&R<=r)return mx[p];down(p);
    20     return max(l<=md?Max(l,r,lc,L,md):0,r>md?Max(l,r,rc,md+1,R):0);
    21 }
    22 void Upd(int x,int p=1,int L=1,int R=n){
    23     if(L==R){mx[p]=mx[p]==S?T:S;return;} down(p);
    24     if(x<=md)Upd(x,lc,L,md);else Upd(x,rc,md+1,R); up(p);
    25 }
    26 int getl(int x,int p=1,int L=1,int R=n){
    27     if(mx[p]!=S)return L;
    28     if(L==R)return R+1;
    29     down(p);
    30     if(x<=md)return getl(x,lc,L,md);
    31     int y=getl(x,rc,md+1,R);return y==md+1?getl(md,lc,L,md):y;
    32 }
    33 int getr(int x,int p=1,int L=1,int R=n){
    34     if(mx[p]!=S)return R;
    35     if(L==R)return L-1;
    36     down(p);
    37     if(x>md)return getr(x,rc,md+1,R);
    38     int y=getr(x,lc,L,md);return y==md?getr(md+1,rc,md+1,R):y;
    39 }
    40 void add(int&p,int l,int r,int v,int L=1,int R=n){
    41     if(!p)p=++pc;//printf("add:%d %d %d %d %d %d
    ",p,l,r,v,L,R);
    42     if(l<=L&&R<=r){w[p]+=v;return;}
    43     if(l<=md)add(Lc[p],l,r,v,L,md); if(r>md)add(Rc[p],l,r,v,md+1,R);
    44 }
    45 int ask(int p,int x,int L=1,int R=n){//printf("ask:%d %d %d %d %d
    ",p,x,L,R,w[p]);
    46     if(!p||L==R)return w[p];
    47     return w[p]+(x<=md?ask(Lc[p],x,L,md):ask(Rc[p],x,md+1,R));
    48 }
    49 void Add(int l,int r,int _l,int _r,int v,int p=1,int L=1,int R=n){
    50     if(l<=L&&R<=r)return add(rt[p],_l,_r,v);
    51     if(l<=md)Add(l,r,_l,_r,v,lc,L,md);if(r>md)Add(l,r,_l,_r,v,rc,md+1,R);
    52 }
    53 int Sum(int x,int y,int p=1,int L=1,int R=n){return ask(rt[p],y)+(L!=R?(x<=md?Sum(x,y,lc,L,md):Sum(x,y,rc,md+1,R)):0);}
    54 int main(){
    55     freopen("segment.in","r",stdin);freopen("segment.out","w",stdout);
    56     scanf("%d%d%s",&n,&q,s+1);
    57     build(1,1,n);
    58     for(int x,l,r;T<=q;++T){
    59         scanf("%s%d",o,&x);
    60         if(o[0]=='t'){
    61             l=getl(x),r=getr(x);
    62             if(s[x]=='1')Add(l,x,x,r,T-Max(l,r));//,printf("operate:%d %d %d %d %d
    ",l,x,x,r,T-Max(l,r));
    63             else{
    64                 l=getl(x-1);r=getr(x+1);
    65                 if(l<x)Add(l,x-1,l,x-1,T-Max(l,x-1)),segset(l,x-1);//,printf("operate:%d %d %d %d %d
    ",l,x-1,l,x-1,T-Max(l,x-1));
    66                 if(r>x)Add(x+1,r,x+1,r,T-Max(x+1,r)),segset(x+1,r);//,printf("operate:%d %d %d %d %d
    ",x+1,r,x+1,r,T-Max(x+1,r));
    67             }
    68             s[x]^=1;Upd(x);
    69         }else{
    70             scanf("%d",&r),r--;
    71             int y=Max(x,r);
    72             if(y==S)printf("%d
    ",Sum(x,r));
    73             else printf("%d
    ",Sum(x,r)+T-Max(getl(x),getr(r)));
    74         }
    75     }
    76 }
    View Code
  • 相关阅读:
    C和C++的不同点
    音频质量评价指标
    常用函数整理
    Subband Decomposition
    Stability Analysis of Algorithms
    Time Frequency (T-F) Masking Technique
    雅克比(Jacobi)方法
    寒假3
    寒假作业二
    寒假 2
  • 原文地址:https://www.cnblogs.com/hzoi-DeepinC/p/13045418.html
Copyright © 2011-2022 走看看