zoukankan      html  css  js  c++  java
  • csp2019备赛之刷题赛-round3

    csp2019备赛之刷题赛-round3

    link to this contest

    C. Winner

    大意:有$n$个人打淘汰赛,每个人有$3$个权值,只要有一个权值大于对方就有可能获胜,问每个人是否有可能夺冠

    $n leq 10^5$

    题解:对于三维权值,每一维都排一次序,权值大的向权值小的连边,如果有权值相同,就开两个出入的虚点,如果存在一条$x-->y$的路径就说明$x$可能打败$y$,然后缩点,没有入度的那个块里面的点都可能拿冠军

      1 #include<bits/stdc++.h>
      2 namespace csx_std {
      3     using namespace std;
      4     typedef long long ll;
      5     #define FOR(i,a,b) for (register int i=(a);i<=(b);i++)
      6     #define For(i,a,b) for (register int i=(a);i>=(b);i--)
      7     #define mem(i,j) memset(i,j,sizeof(i))
      8     #define pii pair<int,int>
      9     #define MP make_pair
     10     #define fi first
     11     #define se second
     12     #define GO(u) for (register int j=first[u];j!=-1;j=nxt[j])
     13     const int N=4e5+5;
     14     const int mod=1e9+7;
     15     inline int qpow(int x,int y) {int ret=1;for (;y;y>>=1,x=1LL*x*x%mod) if (y&1) ret=1LL*ret*x%mod;return ret;}
     16     inline int Inv(int x) {return qpow(x,mod-2);}
     17     inline void upd(int &x,int y) {x=(1LL*x+y)%mod;return;}
     18     inline int chkmax(int &x,int y) {return (x<y)?(x=y,1):0;}
     19     inline int chkmin(int &x,int y) {return (x>y)?(x=y,1):0;}
     20     inline int read()
     21     {
     22         int x=0,f=1;
     23         char c=getchar();
     24         while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
     25         while (c>='0'&&c<='9') {x=(x<<1)+(x<<3)+c-'0';c=getchar();}
     26         return f*x;
     27     }
     28     inline void write(int x)
     29     {
     30         if (x<0) x=-x,putchar('-');
     31         if (x>9) write(x/10);
     32         putchar(x%10+'0');
     33         return;
     34     }
     35 }
     36 using namespace csx_std;
     37 int n,q,Q[N],ans[N],vis[N],dfn[N],low[N],stck[N],dfnn=0;
     38 int bl[N],du[N],cnt,top=0,siz[N],gp=0,tag=0;
     39 int tot=0,first[N],nxt[N];
     40 struct E
     41 {
     42     int u,v;
     43 }e[N];
     44 inline void add(int u,int v)
     45 {
     46     if (!v) return;
     47     tot++;
     48     nxt[tot]=first[u];
     49     first[u]=tot;
     50     e[tot]=(E){u,v};
     51 //    printf("(%d,%d)
    ",u,v);
     52     return;
     53 }
     54 struct data
     55 {
     56     int a,b,c,id;
     57 }f[N];
     58 bool cmp1(const data x,const data y) {return x.a<y.a;}
     59 bool cmp2(const data x,const data y) {return x.b<y.b;}
     60 bool cmp3(const data x,const data y) {return x.c<y.c;}
     61 inline void build()
     62 {
     63     int last=0;
     64     sort(f+1,f+n+1,cmp1);
     65     FOR(i,1,n)
     66     {
     67         int r=i;
     68         while (f[i].a==f[r+1].a) r++;
     69         if (i<r)
     70         {
     71             cnt++;
     72             add(cnt,last);
     73             FOR(j,i,r) add(f[j].id,cnt);
     74             cnt++;
     75             FOR(j,i,r) add(cnt,f[j].id);
     76             last=cnt;
     77         }
     78         else add(f[i].id,last),last=f[i].id;
     79         i=r;
     80     }
     81     
     82     last=0;
     83     sort(f+1,f+n+1,cmp2);
     84     FOR(i,1,n)
     85     {
     86         int r=i;
     87         while (f[i].b==f[r+1].b) r++;
     88         if (i<r)
     89         {
     90             cnt++;
     91             add(cnt,last);
     92             FOR(j,i,r) add(f[j].id,cnt);
     93             cnt++;
     94             FOR(j,i,r) add(cnt,f[j].id );
     95             last=cnt;
     96         }
     97         else add(f[i].id,last),last=f[i].id;
     98         i=r;
     99     }
    100     
    101     last=0;
    102     sort(f+1,f+n+1,cmp3);
    103     FOR(i,1,n)
    104     {
    105         int r=i;
    106         while (f[i].c==f[r+1].c) r++;
    107         if (i<r)
    108         {
    109             cnt++;
    110             add(cnt,last);
    111             FOR(j,i,r) add(f[j].id,cnt);
    112             cnt++;
    113             FOR(j,i,r) add(cnt,f[j].id );
    114             last=cnt;
    115         }
    116         else add(f[i].id,last),last=f[i].id;
    117         i=r;
    118     }
    119     return;
    120 }
    121 inline void Tarjan(int u)
    122 {
    123     dfn[u]=low[u]=++dfnn;
    124     vis[u]=1;
    125     stck[++top]=u;
    126     GO(u)
    127     {
    128         int v=e[j].v;
    129         if (!dfn[v])
    130         {
    131             Tarjan(v);
    132             chkmin(low[u],low[v]);
    133         }
    134         else if (vis[v]) chkmin(low[u],dfn[v]);
    135     }
    136     if (low[u]==dfn[u])
    137     {
    138         gp++;
    139         while (stck[top+1]!=u)
    140         {
    141             bl[stck[top]]=gp;
    142             vis[stck[top]]=0;
    143             if (stck[top]<=n) siz[gp]++;
    144             top--;
    145         }
    146     }
    147     return;
    148 }
    149 int main()
    150 {
    151     mem(first,-1);
    152     n=read(),q=read();
    153     cnt=n;
    154     FOR(i,1,n) f[i].a=read();
    155     FOR(i,1,n) f[i].b=read();
    156     FOR(i,1,n) f[i].c=read();
    157     FOR(i,1,n) f[i].id=i;
    158     FOR(i,1,q) Q[i]=read();
    159     build();
    160     FOR(i,1,cnt) 
    161         if (!dfn[i]) Tarjan(i);
    162     FOR(i,1,tot) if (bl[e[i].u]!=bl[e[i].v]) du[bl[e[i].v]]++;
    163     FOR(i,1,gp) if (!du[i])
    164     {
    165         tag=i;
    166         break;
    167     }
    168     FOR(i,1,n) if (bl[i]==tag) vis[i]=1;
    169     FOR(i,1,q) ans[i]=vis[Q[i]];
    170     FOR(i,1,q)
    171         if (ans[i]) printf("YES
    ");
    172         else printf("NO
    ");
    173     return 0;
    174 }
    175 /*
    176 4 4
    177 1 2 3 4
    178 1 2 4 3
    179 2 1 3 4
    180 1
    181 2
    182 3
    183 4
    184 */
    View Code

    D. Independent set

    大意:给你一个$n$个点$m$条边的无向图,请你求出所有子图的最大独立集大小之和

    $n leq 26,m leq frac{n(n-1)}{2}$

    题解:

    • 设与$i$距离$leq 1$的点集的压缩状态为$edge_i$,$f_S$表示状态$S$的最大独立集大小
    • 于是有转移$f_S=max{f_{S-lowbit(S)},f_{S& (`edge_{ lowbit(S)} ) } }$
     1 #include<bits/stdc++.h>
     2 namespace csx_std {
     3     using namespace std;
     4     typedef long long ll;
     5     #define FOR(i,a,b) for (register int i=(a);i<=(b);i++)
     6     #define For(i,a,b) for (register int i=(a);i>=(b);i--)
     7     #define mem(i,j) memset(i,j,sizeof(i))
     8     #define pii pair<int,int>
     9     #define pb push_back
    10     #define MP make_pair
    11     #define fi first
    12     #define se second
    13     #define GO(u) for (register int j=f[u];j!=-1;j=nxt[j])
    14     const int N=1e5+5;
    15     const int mod=1e9+7;
    16     inline int qpow(int x,int y) {int ret=1;for (;y;y>>=1,x=1LL*x*x%mod) if (y&1) ret=1LL*ret*x%mod;return ret;}
    17     inline int Inv(int x) {return qpow(x,mod-2);}
    18     inline void upd(int &x,int y) {x=(1LL*x+y)%mod;return;}
    19     inline int chkmax(int &x,int y) {return (x<y)?(x=y,1):0;}
    20     inline int chkmin(int &x,int y) {return (x>y)?(x=y,1):0;}
    21     inline int read()
    22     {
    23         int x=0,f=1;
    24         char c=getchar();
    25         while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    26         while (c>='0'&&c<='9') {x=(x<<1)+(x<<3)+c-'0';c=getchar();}
    27         return f*x;
    28     }
    29     inline void write(ll x)
    30     {
    31         if (x<0) x=-x,putchar('-');
    32         if (x>9) write(x/10);
    33         putchar(x%10+'0');
    34         return;
    35     }
    36 }
    37 using namespace csx_std;
    38 int n,m,edge[26],tmp1,tmp2;
    39 char f[1<<26];
    40 ll ans=0;
    41 inline int lowbit(int x) {return x&-x;}
    42 int main()
    43 {
    44     n=read(),m=read();
    45     FOR(i,0,n-1) edge[i]|=1<<i;
    46     FOR(i,1,m)
    47     {
    48         tmp1=read(),tmp2=read();
    49         edge[tmp1]|=1<<tmp2;
    50         edge[tmp2]|=1<<tmp1;
    51     }
    52     FOR(i,1,(1<<n)-1) 
    53     {
    54         int tmp=lowbit(i);
    55         tmp=log2(tmp);
    56         f[i]=max((int)f[i xor lowbit(i)],f[i & (~edge[tmp])]+1);
    57     }
    58     FOR(i,0,(1<<n)-1) ans+=f[i];
    59     write(ans);
    60     return 0;
    61 }
    View Code

    E. Train Driver

    大意:给出一个n个点m条边的无向图,肥宅和死肥宅决定同时追求女神,他们决定以最短的距离去到女神的位置,肥宅的家在点集SA中的某个点(等概率的),死肥宅则在SB中,女神会在图中任意一个点出现(也可以出现在肥宅或者死肥宅的家中),现在你想知道,如果他们3个人要在图中的某个点集合,那么他们所走过的最短路径的期望值是多少?

    $1leq n,m leq 10^5,|SA|,|SB| leq 20$

    题解:

    • 首先,期望改计数,我们要对于$|SA| imes |SB|$种肥宅出没的情况下,女神出现在任意地方的路径总和
    • 首先,大力$BFS$预处理出每个肥宅位到每个点的距离,考虑现在枚举两个肥宅的位置,我们如何知道女神出现在这$n$个点的距离总和,我们令$dis_i=disa_{u,i}+disb_{v,i}$,表示假设女神在$i$的最短距离总和,这么初始化是假设女神不动,然后这些值排个序放进一个队列里面,逐个松弛,新入队的点加入另一个队列(像是个输出值不为$0$的广搜)
      1 #include<bits/stdc++.h>
      2 namespace csx_std {
      3     using namespace std;
      4     typedef long long ll;
      5     #define FOR(i,a,b) for (register int i=(a);i<=(b);i++)
      6     #define For(i,a,b) for (register int i=(a);i>=(b);i--)
      7     #define mem(i,j) memset(i,j,sizeof(i))
      8     #define GO(u) for (register int j=f[u];j!=-1;j=nxt[j])
      9     const int N=2e5+5;
     10     inline int read()
     11     {
     12         int x=0,f=1;
     13         char c=getchar();
     14         while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
     15         while (c>='0'&&c<='9') {x=(x<<1)+(x<<3)+c-'0';c=getchar();}
     16         return f*x;
     17     }
     18 }
     19 using namespace csx_std;
     20 int T,n,m,nsa,nsb,sa[25],sb[25],dis[N],disa[25][N],disb[25][N];
     21 int line[N],l,r,cnt[N<<2],tmp1,tmp2,gcd;
     22 ll ans=0;
     23 queue <int> q;
     24 int tot=0,f[N],nxt[N];
     25 struct E{int u,v;}e[N];
     26 inline void add(int u,int v)
     27 {
     28     tot++;
     29     nxt[tot]=f[u];
     30     f[u]=tot;
     31     e[tot]=(E){u,v};
     32     return;
     33 }
     34 inline int GCD(int x,int y)
     35 {
     36     if (!y) return x;
     37     if (x<y) return GCD(y,x);
     38     return GCD(y,x%y);
     39 }
     40 inline void BFS(int *d,int S)
     41 {
     42     d[S]=0;
     43     while (q.size()) q.pop();
     44     q.push(S);
     45     while (q.size())
     46     {
     47         int u=q.front();
     48         q.pop();
     49         GO(u) if (d[e[j].v]==-1) {d[e[j].v]=d[u]+1;q.push(e[j].v);}
     50     }
     51     return;
     52 }
     53 inline void BFS2()
     54 {
     55     while (q.size()) q.pop();
     56     while (l<=r||q.size())
     57     {
     58         int u;
     59         if (q.size()&&l>r) u=q.front(),q.pop();
     60         else if (q.empty()&&l<=r) u=line[l++];
     61         else if (dis[q.front()]<=dis[line[l]]) u=q.front(),q.pop();
     62         else u=line[l++];
     63         GO(u) if (dis[e[j].v]>dis[u]+1) {dis[e[j].v]=dis[u]+1;q.push(e[j].v);}
     64     }
     65     return;
     66 }
     67 inline void Sort()
     68 {
     69     l=1,r=n;
     70     FOR(i,0,n<<1) cnt[i]=0;
     71     FOR(i,1,n) cnt[dis[i]]++;
     72     FOR(i,1,n<<1) cnt[i]+=cnt[i-1];
     73     For(i,n,1) line[cnt[dis[i]]--]=i;
     74     return;
     75 }
     76 inline void clear()
     77 {
     78     FOR(i,0,n) f[i]=-1;
     79     tot=ans=0;
     80     return;
     81 }
     82 int main()
     83 {
     84 //    freopen("data.in","r",stdin);
     85     mem(f,-1);
     86     T=read();
     87     FOR(Case,1,T)
     88     {
     89         n=read(),m=read();
     90         FOR(i,1,m) tmp1=read(),tmp2=read(),add(tmp1,tmp2),add(tmp2,tmp1);
     91         nsa=read();
     92         FOR(i,1,nsa) sa[i]=read();
     93         nsb=read();
     94         FOR(i,1,nsb) sb[i]=read();
     95         FOR(i,1,nsa) 
     96         {
     97             FOR(j,0,n) disa[i][j]=-1;
     98             BFS(disa[i],sa[i]);
     99         }
    100         FOR(i,1,nsb)
    101         {
    102             FOR(j,0,n) disb[i][j]=-1;
    103             BFS(disb[i],sb[i]);
    104         } 
    105         FOR(i,1,nsa) FOR(j,1,nsb)
    106         {
    107             FOR(k,1,n) dis[k]=disa[i][k]+disb[j][k];
    108             Sort();
    109             BFS2();
    110             FOR(k,1,n) ans+=dis[k];
    111         }
    112         gcd=GCD(ans,1LL*nsa*nsb*n);
    113         printf("Case #%d: %lld/%lld
    ",Case,ans/gcd,1LL*nsa*nsb*n/gcd);
    114         clear();
    115     }
    116     return 0;
    117 }
    View Code

    F. Explorer

    大意:给定一张无向图,每条边有权值范围$[l_i,r_i]$,要经过这条边的条件是你的容量要在$[l_i,r_i]$,现在问你有多少种容量,使得你能从$1$走到$n$

    $n,m leq 10^5 , l,r leq 10^9$

    题解:线段树分治加可撤销并查集,其中我们需要把权值区间离散化,那么我们线段树上的节点不能再使用闭区间了,否则$(mid,mid+1)$之间的权值会蒸发,改成左闭右开的区间就行了

      1 #include<bits/stdc++.h>
      2 namespace csx_std {
      3     using namespace std;
      4     typedef long long ll;
      5     #define FOR(i,a,b) for (register int i=(a);i<=(b);i++)
      6     #define For(i,a,b) for (register int i=(a);i>=(b);i--)
      7     #define mem(i,j) memset(i,j,sizeof(i))
      8     #define pii pair<int,int>
      9     #define pb push_back
     10     #define MP make_pair
     11     #define fi first
     12     #define se second
     13     #define GO(u) for (register int j=first[u];j!=-1;j=nxt[j])
     14     const int N=3e5+5;
     15     const int mod=1e9+7;
     16     inline int qpow(int x,int y) {int ret=1;for (;y;y>>=1,x=1LL*x*x%mod) if (y&1) ret=1LL*ret*x%mod;return ret;}
     17     inline int Inv(int x) {return qpow(x,mod-2);}
     18     inline void upd(int &x,int y) {x=(1LL*x+y)%mod;return;}
     19     inline int chkmax(int &x,int y) {return (x<y)?(x=y,1):0;}
     20     inline int chkmin(int &x,int y) {return (x>y)?(x=y,1):0;}
     21     inline int read()
     22     {
     23         int x=0,f=1;
     24         char c=getchar();
     25         while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
     26         while (c>='0'&&c<='9') {x=(x<<1)+(x<<3)+c-'0';c=getchar();}
     27         return f*x;
     28     }
     29     inline void write(ll x)
     30     {
     31         if (x<0) x=-x,putchar('-');
     32         if (x>9) write(x/10);
     33         putchar(x%10+'0');
     34         return;
     35     }
     36 }
     37 using namespace csx_std;
     38 int n,m,fa[N],dep[N];
     39 ll ans=0,b[N<<1],len=0;
     40 int in1[N],in2[N],in3[N],in4[N];
     41 struct data
     42 {
     43     int u,v,w;
     44 };
     45 vector <data> vec[N<<2];
     46 inline int getfa(int x) {return (x==fa[x])?x:getfa(fa[x]);}
     47 inline int con(int x,int y)
     48 {
     49     int fx=getfa(x),fy=getfa(y);
     50     return (fx==fy);
     51 }
     52 inline data link(int x,int y)
     53 {
     54     data ret;
     55     int fx=getfa(x),fy=getfa(y);
     56     if (dep[fx]>dep[fy]) swap(x,y),swap(fx,fy);
     57     ret.u=fx,ret.v=fy;
     58     fa[fx]=fy;
     59     if (dep[fx]==dep[fy]) dep[fy]++,ret.w=1;
     60     else ret.w=0;
     61     return ret;
     62 }
     63 inline void del(vector <data> V)
     64 {
     65     For(i,(int)V.size()-1,0)
     66     {
     67         dep[V[i].v]-=V[i].w;
     68         fa[V[i].u]=V[i].u;
     69     }
     70     return;
     71 }
     72 inline void insert(int p,int l,int r,int L,int R,int ith)
     73 {
     74     if (L<=l&&r<=R) {vec[p].pb((data){in1[ith],in2[ith],0});return;}
     75     if (l==r-1) return;
     76     int mid=(l+r)>>1;
     77     if (L<=mid) insert(p<<1,l,mid,L,R,ith);
     78     if (R>mid) insert(p<<1|1,mid,r,L,R,ith);
     79     return;
     80 }
     81 inline void solve(int p,int l,int r)
     82 {
     83     vector <data> rub;
     84     rub.clear();
     85     FOR(i,0,(int)vec[p].size()-1) if (!con(vec[p][i].u,vec[p][i].v)) rub.pb(link(vec[p][i].u,vec[p][i].v));
     86     if (con(1,n)) {ans+=b[r]-b[l];del(rub);return;}
     87     if (l==r-1) {del(rub);return;}
     88     int mid=(l+r)>>1;
     89     solve(p<<1,l,mid);
     90     solve(p<<1|1,mid,r);
     91     del(rub);
     92     return;
     93 }
     94 inline void debug(int p,int l,int r)
     95 {
     96     printf("[%d,%d] : 
    ",l,r);
     97     FOR(i,0,(int)vec[p].size()-1)
     98     {
     99         printf("(%d,%d) ",vec[p][i].u,vec[p][i].v);
    100     }
    101     putchar('
    ');
    102     int mid=(l+r)>>1;
    103     if (l==r) return;
    104     debug(p<<1,l,mid);
    105     debug(p<<1|1,mid+1,r);
    106     return;
    107 }
    108 int main()
    109 {
    110     n=read(),m=read();
    111     FOR(i,1,n) fa[i]=i,dep[i]=1;
    112     FOR(i,1,m) in1[i]=read(),in2[i]=read(),in3[i]=read(),in4[i]=read()+1,b[++len]=in3[i],b[++len]=in4[i];
    113     sort(b+1,b+len+1);
    114     len=unique(b+1,b+len+1)-b-1;
    115     FOR(i,1,m) in3[i]=lower_bound(b+1,b+len+1,in3[i])-b,in4[i]=lower_bound(b+1,b+len+1,in4[i])-b;
    116     FOR(i,1,m) insert(1,1,len,in3[i],in4[i],i);
    117     solve(1,1,len);
    118     write(ans),putchar('
    ');
    119 //    debug(1,1,len);
    120     return 0;
    121 }
    122 /*
    123 5 5
    124 1 2 10 40
    125 2 3 10 20
    126 3 5 20 40
    127 2 4 10 30
    128 4 5 20 40
    129 */
    View Code

    G. Inner World

    大意:有$n$棵树,一开始都只有一个$1$号节点,先有$m$个种植操作,后有$q$个询问操作

    • 种植操作形如$u,v,l,r$,表示$[l,r]$的树上的$u$号节点多了一个$v$号儿子(保证每次的$v$互不相同)
    • 询问操作形如$x,l,r$,表示询问$[l,r]$的树上的$x$号节点的子树大小之和

    题解:

    • 由于每次的$v$互补相同,那么每个点出现的位置是连续区间,并且如果我们把所有种植操作集中在一棵树上,那么所有的树都会是这棵树的子图
    • 我们给这棵树表上$dfs$序,那么我们把树的下标和$dfs$序看作二维空间,每个种植操作相当于给一个线段加上$1$,每个询问操作相当于问某个矩形内的和
    • 我们扫描线枚举$dfs$序这一维,把询问拆开塞到某两个$dfs$序位置即可,线段树维护区间加,区间询问
      1 #include<bits/stdc++.h>
      2 namespace csx_std {
      3     using namespace std;
      4     typedef long long ll;
      5     #define FOR(i,a,b) for (register ll i=(a);i<=(b);i++)
      6     #define mem(i,j) memset(i,j,sizeof(i))
      7     #define pb push_back
      8     #define GO(u) for (register ll j=f[u];j!=-1;j=nxt[j])
      9     const ll N=3e5+5;
     10     inline ll read()
     11     {
     12         ll x=0,f=1;
     13         char c=getchar();
     14         while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
     15         while (c>='0'&&c<='9') {x=(x<<1)+(x<<3)+c-'0';c=getchar();}
     16         return f*x;
     17     }
     18     inline void write(ll x)
     19     {
     20         if (x<0) x=-x,putchar('-');
     21         if (x>9) write(x/10);
     22         putchar(x%10+'0');
     23         return;
     24     }
     25 }
     26 using namespace csx_std;
     27 ll n,m,tmp1,tmp2,tmp3,tmp4,L[N],R[N],q,ans[N];
     28 ll tot=0,f[N],nxt[N],back[N],l[N],r[N],dfnn=0;
     29 struct E {ll u,v;}e[N];
     30 inline void Add(ll u,ll v)
     31 {
     32     tot++;
     33     nxt[tot]=f[u];
     34     f[u]=tot;
     35     e[tot]=(E){u,v};
     36     return;
     37 }
     38 struct data{ll id,l,r,fh;};
     39 vector <data> G[N];
     40 inline void dfs(ll u)
     41 {
     42     l[u]=++dfnn;
     43     back[dfnn]=u;
     44     GO(u) dfs(e[j].v);
     45     r[u]=dfnn;
     46     return;
     47 }
     48 ll t[N<<2],tag[N<<2];
     49 #define mid ((l+r)>>1)
     50 #define ls p<<1
     51 #define rs p<<1|1
     52 #define lson ls,l,mid
     53 #define rson rs,mid+1,r
     54 inline void up(ll p) {t[p]=t[ls]+t[rs];return;}
     55 inline void down(ll p,ll l,ll r)
     56 {
     57     if (!tag[p]) return;
     58     t[ls]+=(mid-l+1)*tag[p];
     59     t[rs]+=(r-mid)*tag[p];
     60     tag[ls]+=tag[p],tag[rs]+=tag[p];
     61     tag[p]=0;return;
     62 }
     63 inline void md(ll p,ll l,ll r,ll L,ll R,ll v)
     64 {
     65     if (L<=l&&r<=R) {t[p]+=(r-l+1)*v;tag[p]+=v;return;}
     66     down(p,l,r);
     67     if (L<=mid) md(lson,L,R,v);
     68     if (R>mid) md(rson,L,R,v);
     69     up(p);return;
     70 }
     71 inline ll qr(ll p,ll l,ll r,ll L,ll R)
     72 {
     73     if (L<=l&&r<=R) return t[p];
     74     down(p,l,r);
     75     ll ret=0;
     76     if (L<=mid) ret+=qr(lson,L,R);
     77     if (R>mid) ret+=qr(rson,L,R);
     78     up(p);return ret;
     79 }
     80 #undef mid
     81 #undef ls
     82 #undef rs
     83 #undef lson
     84 #undef rson
     85 int main()
     86 {
     87 //    freopen("data.in","r",stdin);
     88 //    freopen("myans.out","w",stdout);
     89     mem(f,-1);
     90     n=read(),m=read();
     91     L[1]=1,R[1]=n;
     92     FOR(i,1,m) tmp1=read(),tmp2=read(),tmp3=read(),tmp4=read(),Add(tmp1,tmp2),L[tmp2]=tmp3,R[tmp2]=tmp4;
     93     dfs(1);
     94     q=read();
     95     FOR(i,1,q) 
     96     {
     97         tmp1=read(),tmp2=read(),tmp3=read();
     98         G[l[tmp1]-1].pb((data){i,tmp2,tmp3,-1});
     99         G[r[tmp1]].pb((data){i,tmp2,tmp3,1});
    100     }
    101     FOR(i,1,dfnn)
    102     {
    103         ll u=back[i];
    104         md(1,1,n,L[u],R[u],1);
    105         FOR(j,0,(ll)G[i].size()-1)
    106             ans[G[i][j].id]+=G[i][j].fh*qr(1,1,n,G[i][j].l,G[i][j].r);
    107     }
    108     FOR(i,1,q) write(ans[i]),putchar('
    ');
    109     return 0;
    110 }
    View Code

    H. Jump Frog

    大意:有个青蛙要从$0$跳到$n$,每次至少跳$d$,其中有$m$个限制形如$t_i,p_i$,表示第$t_i$步不能跳到$p_i$问有多少种方案

    $n,d leq 10^9,m leq 3000$

    题解:

    • 我们称一个限制为一个关键点,答案就是总方案减去经过关键点的方案,关键点按步数排序
    • 设$cal(x,y)$为$y$步跳$x$距离的方案数,插板法$O(1)$计算,设$g_i$为跳距离$i$的方案数,$DP$计算
    • 枚举第一个经过的关键点,设从$0$不经过任何关键点到第$i$个关键点的方案是$dp_i$,那么$Ans=sum dp_i imes g_{n-p_i}$
    • 考虑平方的转移求出$dp$数组,$dp_i=cal(0,t_i)-sum_{j=1}^{i-1} dp_j imes cal(p_i-p_j,t_i-t_j)$
    • 总之这题就是大力容斥
     1 #include<bits/stdc++.h>
     2 namespace csx_std {
     3     using namespace std;
     4     typedef long long ll;
     5     #define FOR(i,a,b) for (register ll i=(a);i<=(b);i++)
     6     #define For(i,a,b) for (register ll i=(a);i>=(b);i--)
     7     #define mem(i,j) memset(i,j,sizeof(i))
     8     #define pii pair<ll,ll>
     9     #define pb push_back
    10     #define MP make_pair
    11     #define fi first
    12     #define se second
    13     #define GO(u) for (register ll j=f[u];j!=-1;j=nxt[j])
    14     const ll N=3030;
    15     const ll M=1e7+5;
    16     const ll mod=998244353;
    17     inline ll qpow(ll x,ll y) {ll ret=1;for (;y;y>>=1,x=1LL*x*x%mod) if (y&1) ret=1LL*ret*x%mod;return ret;}
    18     inline ll Inv(ll x) {return qpow(x,mod-2);}
    19     inline void upd(ll &x,ll y) {x=(1LL*x+y)%mod;return;}
    20     inline ll read()
    21     {
    22         ll x=0,f=1;
    23         char c=getchar();
    24         while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    25         while (c>='0'&&c<='9') {x=(x<<1)+(x<<3)+c-'0';c=getchar();}
    26         return f*x;
    27     }
    28     inline void write(ll x)
    29     {
    30         if (x<0) x=-x,putchar('-');
    31         if (x>9) write(x/10);
    32         putchar(x%10+'0');
    33         return;
    34     }
    35 }
    36 using namespace csx_std;
    37 ll n,d,m,g[M],sum_g[M],fac[M],inv[M],dp[N],ans=0;
    38 struct data {ll t,p;}f[N];
    39 bool operator <(data x,data y) {return x.t<y.t;}
    40 inline ll C(ll x,ll y) {if (x<y) return 0;return 1LL*fac[x]*inv[y]%mod*inv[x-y]%mod;}
    41 inline ll cal(ll x,ll y) {return C(x-y*(d-1)-1,y-1);}
    42 int main()
    43 {
    44 //    freopen("data.in","r",stdin);
    45 //    freopen("myans.out","w",stdout);
    46     n=read(),d=read(),m=read();
    47     FOR(i,1,m) f[i].t=read(),f[i].p=read();
    48     sort(f+1,f+m+1);
    49     g[0]=fac[0]=1;
    50     FOR(i,1,n) fac[i]=1LL*fac[i-1]*i%mod;
    51     inv[n]=Inv(fac[n]);
    52     For(i,n-1,0) inv[i]=1LL*inv[i+1]*(i+1)%mod;
    53     FOR(i,0,d-1) sum_g[i]=1;
    54     FOR(i,d,n) g[i]=sum_g[i-d],sum_g[i]=(1LL*sum_g[i-1]+g[i])%mod;
    55     FOR(i,1,m)
    56     {
    57         ll ban=0;
    58         FOR(j,0,i-1) if (f[j].p<=f[i].p)
    59             upd(ban,1LL*dp[j]*cal(f[i].p-f[j].p,f[i].t-f[j].t)%mod);
    60         dp[i]=(1LL*cal(f[i].p,f[i].t)-ban+mod)%mod;
    61     }
    62     FOR(i,1,m) upd(ans,1LL*dp[i]*g[n-f[i].p]%mod);
    63     ans=(1LL*g[n]-ans+mod)%mod;
    64     write(ans),putchar('
    ');
    65     return 0;
    66 }
    View Code
  • 相关阅读:
    shell习题第21题:计算数字的个数
    shell习题第20题:统计文件大小
    萌新小白
    编程第一天
    萌新报道
    linux下安装php扩展pdo_oci和oci8
    安装Hadoop伪分布式踩过的坑
    zabbix安装过程
    MySQL_索引
    mysql复制
  • 原文地址:https://www.cnblogs.com/C-S-X/p/11791641.html
Copyright © 2011-2022 走看看