• 20190922 模拟


    Task1

    这个是USACO 2019 JAN Gold的原题,可能因为过于水,所以我即使八点多才开始做也提前ak。。。来写一篇题解。。

    A. Cow Poetry

    显然押同一韵的行只需要最后一个词属于一个韵部,前面长度$K-s_i$随便排,DP一下长度$i$的有多少种,类似于背包转移,只是把物品放在内层,容量放在外层枚举,这样保证顺序不同时有不同的种类数。

    然后对于每一种要求韵相同的行,可以枚举每一种韵,结合乘法原理和加法原理得出方案数。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<cmath>
     6 #define dbg(x) cerr << #x << " = " << x <<endl
     7 using namespace std;
     8 typedef long long ll;
     9 typedef double db;
    10 typedef pair<int,int> pii;
    11 template<typename T>inline T _min(T A,T B){return A<B?A:B;}
    12 template<typename T>inline T _max(T A,T B){return A>B?A:B;}
    13 template<typename T>inline char MIN(T&A,T B){return A>B?(A=B,1):0;}
    14 template<typename T>inline char MAX(T&A,T B){return A<B?(A=B,1):0;}
    15 template<typename T>inline void _swap(T&A,T&B){A^=B^=A^=B;}
    16 template<typename T>inline T read(T&x){
    17     x=0;int f=0;char c;while(!isdigit(c=getchar()))if(c=='-')f=1;
    18     while(isdigit(c))x=x*10+(c&15),c=getchar();return f?x=-x:x;
    19 }
    20 const int N=5000+7,P=1e9+7;
    21 char opt[3];
    22 int f[N],now;
    23 int cnt[27],typ[N];
    24 int s[N],c[N];
    25 int n,m,k,maxc,ans=1;
    26 inline void add(int&A,int B){A+=B;A>=P&&(A-=P);}
    27 inline int fpow(int x,int p){int ret=1;for(;p;p>>=1,x=x*1ll*x%P)if(p&1)ret=ret*1ll*x%P;return ret;}
    28 
    29 int main(){//freopen("test.in","r",stdin);//freopen("test.ans","w",stdout);
    30     read(n),read(m),read(k);
    31     for(register int i=1;i<=n;++i)read(s[i]),MAX(maxc,read(c[i]));
    32     for(register int i=1;i<=m;++i)scanf("%s",opt),++cnt[opt[0]-'A'];
    33     f[0]=1;
    34     for(register int i=0;i<=k;++i)
    35         for(register int j=1;j<=n;++j)if(i+s[j]<=k)add(f[i+s[j]],f[i]);
    36     for(register int i=1;i<=n;++i)if(k>=s[i])add(typ[c[i]],f[k-s[i]]);
    37     for(register int i=0;i<26;++i)if(cnt[i]){
    38         int tmp=0;
    39         for(register int j=1;j<=maxc;++j)if(typ[j]){
    40             add(tmp,fpow(typ[j],cnt[i]));
    41         }
    42         ans=ans*1ll*tmp%P;
    43     }
    44     printf("%d
    ",ans);
    45     return 0;
    46 }
    View Code

    B. Sleepy Cow Sorting

    这个真的水。。可以发现显然最后最长的有序上升序列不要动,把前面的数不断往后插,这样就保证了次数最少。于是BIT维护一发即可。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<cmath>
     6 #define dbg(x) cerr << #x << " = " << x <<endl
     7 using namespace std;
     8 typedef long long ll;
     9 typedef double db;
    10 typedef pair<int,int> pii;
    11 template<typename T>inline T _min(T A,T B){return A<B?A:B;}
    12 template<typename T>inline T _max(T A,T B){return A>B?A:B;}
    13 template<typename T>inline char MIN(T&A,T B){return A>B?(A=B,1):0;}
    14 template<typename T>inline char MAX(T&A,T B){return A<B?(A=B,1):0;}
    15 template<typename T>inline void _swap(T&A,T&B){A^=B^=A^=B;}
    16 template<typename T>inline T read(T&x){
    17     x=0;int f=0;char c;while(!isdigit(c=getchar()))if(c=='-')f=1;
    18     while(isdigit(c))x=x*10+(c&15),c=getchar();return f?x=-x:x;
    19 }
    20 const int N=1e5+7;
    21 int C[N];
    22 int a[N];
    23 int n,las,pos;
    24 #define lowbit(x) x&(-x)
    25 inline void add(int x){for(;x<=n;x+=lowbit(x))++C[x];}
    26 inline int sum(int x){int ret=0;for(;x;x-=lowbit(x))ret+=C[x];return ret;}
    27 
    28 int main(){//freopen("test.in","r",stdin);//freopen("test.ans","w",stdout);
    29     read(n);
    30     for(register int i=1;i<=n;++i)read(a[i]);
    31     las=a[n];add(las);pos=n-1;
    32     for(register int i=n-1;i;--i)if(MIN(las,a[i]))--pos,add(a[i]);else break;
    33     printf("%d
    ",pos);
    34     for(register int i=1;i<=pos;++i)printf("%d ",pos-i+sum(a[i])),add(a[i]);
    35     puts("");return 0;
    36 }
    View Code

    C. Shortcut

    每个点到根的最短路路径是唯一的(因为字典序已经要求最小的),所以构成的最短路树就是唯一的,于是跑一遍dijkstra记录父边(注意更新min)之后在最短路树上暴力枚举把哪个和根相连,计算贡献取max即可。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<cmath>
     6 #include<queue>
     7 #define dbg(x) cerr << #x << " = " << x <<endl
     8 using namespace std;
     9 typedef long long ll;
    10 typedef double db;
    11 typedef pair<int,int> pii;
    12 template<typename T>inline T _min(T A,T B){return A<B?A:B;}
    13 template<typename T>inline T _max(T A,T B){return A>B?A:B;}
    14 template<typename T>inline char MIN(T&A,T B){return A>B?(A=B,1):0;}
    15 template<typename T>inline char MAX(T&A,T B){return A<B?(A=B,1):0;}
    16 template<typename T>inline void _swap(T&A,T&B){A^=B^=A^=B;}
    17 template<typename T>inline T read(T&x){
    18     x=0;int f=0;char c;while(!isdigit(c=getchar()))if(c=='-')f=1;
    19     while(isdigit(c))x=x*10+(c&15),c=getchar();return f?x=-x:x;
    20 }
    21 const int N=1e5+7;
    22 struct thxorz{int to,nxt,w;}G[N];
    23 int Head[N],tot,c[N];
    24 int n,m,t;
    25 inline void Addedge(int x,int y,int z){
    26     G[++tot].to=y,G[tot].nxt=Head[x],Head[x]=tot,G[tot].w=z;
    27     G[++tot].to=x,G[tot].nxt=Head[y],Head[y]=tot,G[tot].w=z;
    28 }
    29 int dis[N],fa[N],val[N];
    30 priority_queue<pii,vector<pii>,greater<pii> > q;
    31 #define y G[j].to
    32 inline void dij(){
    33     memset(fa,0x3f,sizeof fa);
    34     memset(dis,0x3f,sizeof dis);q.push(make_pair(dis[1]=0,1));
    35     while(!q.empty()){
    36         int d=q.top().first,x=q.top().second;q.pop();
    37         if(dis[x]^d)continue;
    38         for(register int j=Head[x];j;j=G[j].nxt)
    39             if(d+G[j].w==dis[y]&&MIN(fa[y],x))val[y]=G[j].w;
    40             else if(d+G[j].w<dis[y])q.push(make_pair(dis[y]=d+G[j].w,y)),fa[y]=x,val[y]=G[j].w;
    41     }
    42 }
    43 ll ans=0;
    44 int dfs(int x,int fa,int dep){
    45     int siz=c[x];
    46     for(register int j=Head[x];j;j=G[j].nxt)if(y^fa)siz+=dfs(y,x,dep+G[j].w);
    47     MAX(ans,(dep-t)*1ll*siz);
    48     return siz;
    49 }
    50 #undef y
    51 int main(){//freopen("test.in","r",stdin);//freopen("test.ans","w",stdout);
    52     read(n),read(m),read(t);
    53     for(register int i=1;i<=n;++i)read(c[i]);
    54     for(register int i=1,x,y,z;i<=m;++i)read(x),read(y),read(z),Addedge(x,y,z);
    55     dij();memset(Head,0,sizeof Head);tot=0;
    56     for(register int i=2;i<=n;++i)Addedge(i,fa[i],val[i]);
    57     dfs(1,0,0);
    58     printf("%lld
    ",ans);
    59     return 0;
    60 }
    View Code

    Task2

    A. Redistricting

    简化题意:01序列划分块,每块最多$K$个,最小化:块内1个数大于等于0个数的块数。

    列出dp式子

    $f_i=min{f_j+[s_i-s_jge lfloorfrac{i-j+1}{2} floor]}$

    其中$s_i$是G数量前缀和。

    然后那个判断式只能是$0/1$,可以用单调队列维护一个$f$单调不减的序列,新元素小于队尾的肯定更优(因为最多相差1),当相等时讨论,如果这两个元素之间的1数量大于等于0数量,之前决策一定不优,因为选他只会增加1相对于0的数量。

    然后用这两个条件维护队列即可。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<cmath>
     6 #define dbg(x) cerr << #x << " = " << x <<endl
     7 using namespace std;
     8 typedef long long ll;
     9 typedef double db;
    10 typedef pair<int,int> pii;
    11 template<typename T>inline T _min(T A,T B){return A<B?A:B;}
    12 template<typename T>inline T _max(T A,T B){return A>B?A:B;}
    13 template<typename T>inline char MIN(T&A,T B){return A>B?(A=B,1):0;}
    14 template<typename T>inline char MAX(T&A,T B){return A<B?(A=B,1):0;}
    15 template<typename T>inline void _swap(T&A,T&B){A^=B^=A^=B;}
    16 template<typename T>inline T read(T&x){
    17     x=0;int f=0;char c;while(!isdigit(c=getchar()))if(c=='-')f=1;
    18     while(isdigit(c))x=x*10+(c&15),c=getchar();return f?x=-x:x;
    19 }
    20 const int N=3e5+7;
    21 int a[N],f[N],q[N],n,k,l,r;
    22 char s[N];
    23 
    24 int main(){//freopen("testdata.in","r",stdin);//freopen("test.ans","w",stdout);
    25     read(n),read(k);
    26     scanf("%s",s+1);
    27     for(register int i=1;i<=n;++i)a[i]+=a[i-1]+(s[i]=='G');
    28     q[l=r=1]=0;
    29     for(register int i=1;i<=n;++i){
    30         while(l<=r&&q[l]<i-k)++l;
    31         f[i]=f[q[l]]+(a[i]-a[q[l]]>=i-q[l]+1>>1);//dbg(i),dbg(f[i]);
    32         while(l<=r&&(f[q[r]]>f[i]||f[q[r]]==f[i]&&a[i]-a[q[r]]>=i-q[r]+1>>1))--r;
    33         q[++r]=i;
    34     }
    35     printf("%d
    ",f[n]);
    36     return 0;
    37 }
    View Code

    B. Exercise

    题意:就是说给一棵树,然后有一堆非树边,问这张图有多少简单环恰好包含两条非树边。

    首先由一个非常神仙的结论,对于两条非树边,他们对应的路径必须有相交的边才可以在一个环内。

    反正我是真的想不到。。然后还不知道为什么他就是对的,坑了几个小时,配合各种大力分类,感觉是可以理解一点了。。

    比如说一条非树边对应两点$x,y$,另外一条非树边的一点$a$希望走到$x$、跳到$y$然后再走到$b$。一个显然的套路是把非树边转化为树链。

    如果$a$在$x$子树内,$b$只要不同时在其子树内即可。$a$不在子树内,那么寻找一条树上路径$a o x$,然后跳到$y$。因为要求路径上的点不重合,所以$y$出发,不能走到之前走过的地方,也就是要“提前拐弯”走别的路,这样,$a o x o y o b$的路径在树链$x,y$上没有交,又发现,树链上有一小段路没有走过,画一下发现$a$出发到达这个地方直接走这段路后可以直接到$b$,也就是说,$a,b$和$x,y$的树链有相交部分,才可以有点不重复路径,换言之就是简单环。然后发现上述两种分类都成立。

    所以问题就转化为若干个树链有多少对有相交部分。

    先考虑序列上给若干个区间,显然做法是每一个区间统计它后面有多少区间和他相交(不然会算两次),也就是后面起点在$[L_i,R_i]$的区间个数,这个直接用前缀和就行了,注意:对于起点相同的区间,每个区间都会去统计另外几个,注意减去多余的。

    放到树上,一个树链拆成两个直上直下的链,看有多少其他链至少和其中一个相交,方法类似,相当于从根向下的一条链上一个区间,有多少其他区间和他相交。这里注意几点:必须统计起点(指靠上的点)落在这个区间内部的区间个数,如果是结束点会有问题。。我一开始就是挂在这里的,有一种两条链中间相交然后分叉的反例。另外,也要注意两种重复的情况:一种是链起始边相同会造成重复统计,这个记录同一条边作为起始边个数,另一种是拆出来的两条链和问的两条链都有相交,这个用map塞pair统计解决。

    并不是很容易说。。个人也没有很深入的理解。。具体还是要看代码。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<cmath>
     6 #include<queue>
     7 #include<map>
     8 #define mst(x) memset(x,0,sizeof x)
     9 #define dbg(x) cerr << #x << " = " << x <<endl
    10 #define dbg2(x,y) cerr<< #x <<" = "<< x <<"  "<< #y <<" = "<< y <<endl
    11 using namespace std;
    12 typedef long long ll;
    13 typedef double db;
    14 typedef pair<int,int> pii;
    15 template<typename T>inline T _min(T A,T B){return A<B?A:B;}
    16 template<typename T>inline T _max(T A,T B){return A>B?A:B;}
    17 template<typename T>inline char MIN(T&A,T B){return A>B?(A=B,1):0;}
    18 template<typename T>inline char MAX(T&A,T B){return A<B?(A=B,1):0;}
    19 template<typename T>inline void _swap(T&A,T&B){A^=B^=A^=B;}
    20 template<typename T>inline T read(T&x){
    21     x=0;int f=0;char c;while(!isdigit(c=getchar()))if(c=='-')f=1;
    22     while(isdigit(c))x=x*10+(c&15),c=getchar();return f?x=-x:x;
    23 }
    24 const int N=2e5+7;
    25 struct thxorz{
    26     int head[N],nxt[N<<1],to[N<<1],tot;
    27     thxorz(){tot=1;}
    28     inline void add(int x,int y){
    29         to[++tot]=y,nxt[tot]=head[x],head[x]=tot;
    30         to[++tot]=x,nxt[tot]=head[y],head[y]=tot;
    31     }
    32 }G;
    33 map<pii,int> mp;
    34 int qx[N],qy[N],lca[N];
    35 int n,m,tmp;
    36 ll ans;
    37 #define y G.to[j]
    38 int dep[N],son[N],sum[N],fa[N],topfa[N],st[N];
    39 void dfs0(int x,int fat){
    40     fa[x]=fat,dep[x]=dep[fat]+1,sum[x]=1;int tmp=-1;
    41     for(register int j=G.head[x];j;j=G.nxt[j])if(y^fat)dfs0(y,x),sum[x]+=sum[y],MAX(tmp,sum[y])&&(son[x]=y);
    42 }
    43 void dfs1(int x,int topf){
    44     topfa[x]=topf;if(!son[x])return;dfs1(son[x],topf);
    45     for(register int j=G.head[x];j;j=G.nxt[j])if(y^fa[x]&&y^son[x])dfs1(y,y);
    46 }
    47 void dfs2(int x){for(register int j=G.head[x];j;j=G.nxt[j])if(y^fa[x])st[y]+=st[x],dfs2(y);}
    48 #undef y
    49 inline int LCA(int x,int y){
    50     while(topfa[x]^topfa[y])dep[topfa[x]]>dep[topfa[y]]?x=fa[topfa[x]]:y=fa[topfa[y]];
    51     return dep[x]<dep[y]?x:y;
    52 }
    53 inline int jump(int x,int lca){
    54     int las=0;
    55     while(topfa[x]^topfa[lca])las=topfa[x],x=fa[las];
    56     return x==lca?las:son[lca];
    57 }
    58 
    59 int main(){freopen("exercise.in","r",stdin);freopen("exercise.out","w",stdout);
    60     read(n),m=read(m)-n+1;
    61     for(register int i=1,x,y;i<n;++i)read(x),read(y),G.add(x,y);
    62     dfs0(1,0),dfs1(1,1);
    63     for(register int i=1,bx,by;i<=m;++i){
    64         read(qx[i]),read(qy[i]);
    65         lca[i]=LCA(qx[i],qy[i]);
    66         if(lca[i]^qx[i])bx=jump(qx[i],lca[i]),ans-=++st[bx];
    67         if(lca[i]^qy[i])by=jump(qy[i],lca[i]),ans-=++st[by];
    68         if(lca[i]^qx[i]&&lca[i]^qy[i]){
    69             if(bx>by)_swap(bx,by);
    70             ans-=mp[make_pair(bx,by)]++;
    71         }
    72     }
    73     dfs2(1);
    74     for(register int i=1;i<=m;++i)ans+=st[qx[i]]+st[qy[i]]-(st[lca[i]]<<1);
    75     printf("%lld
    ",ans);
    76     return 0;
    77 }
    View Code

    C. tracking2

    神仙计数题,不会,自闭中。。。

    To be continued.

  • 相关阅读:
    最艰难的采访IT公司ThoughtWorks代码挑战——FizzBuzzWhizz游戏
    SQL Server 存储字符数较大字段的问题
    c# var的含义与用法
    ListBox和ComboBox绑定数据简单例子
    “C# 未在本地计算机上注册microsoft.Jet.OLEDB.12.0”的解决方案
    [转] c# 操作Word
    C++ Regsvr32订购具体解释
    数字计算的有序排列的号码出现二分法
    合作信息处理模型
    内存四个领域,变量声明和定义,注册,c内联汇编,auto,堆,不变,静态变量
  • 原文地址:https://www.cnblogs.com/saigyouji-yuyuko/p/11566642.html
Copyright © 2020-2023  润新知