T1 ZYB和售货机


容易发现把每个物品都买成$1$是没有影响的。

然后考虑最后一个物品的方案,如果从$f_i$向$i$连边,发现每个点有一个出度多个入度,可以先默认每个物品都能买且最大获利,这样可以建出每个点出度入度都是$1$的图。

把所有边都连上是一个基环树,所以建出的若干个联通图中只有一个环。而我们要做的工作就是用最小代价把这个环断掉,形成的树上所有边都可以对答案贡献。

记每个物品的最大获利和次大获利,在图上$DFS$,每到一个点先加上最大获利,记录路径上最大获利与次大获利差的最小值,如果当前这一块是环,把答案减去这个最小值即可。

$code:$

 1 #include<bits/stdc++.h>
2 #define int long long
3 using namespace std;
4
5 namespace IO{
6 inline int read(){
7 char ch=getchar(); int x=0,f=1;
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 inline void write(int x,char sp){
13 char ch[20]; int len=0;
14 if(x<0){ putchar('-'); x=~x+1; }
15 do{ ch[len++]=x%10+(1<<4)+(1<<5); x/=10; }while(x);
16 for(int i=len-1;~i;--i) putchar(ch[i]); putchar(sp);
17 }
18 inline int max(int x,int y){ return x<y?y:x; }
19 inline int min(int x,int y){ return x<y?x:y; }
20 inline void swap(int &x,int &y){ x^=y^=x^=y; }
21 inline void chmax(int &x,int y){ x=x<y?y:x; }
22 inline void chmin(int &x,int y){ x=x<y?x:y; }
23 } using namespace IO;
24
25 const int NN=1e6+5;
26 int n,st,ans,cnt,mn,bel[NN],f[NN],c[NN],d[NN],a[NN],mx[NN],sc[NN],val[NN];
27 bool vis[NN];
28
29 void dfs(int x){
30 if(bel[x]==cnt) return ans-=mn,void();
31 if(bel[x]) return;
32 if(!mx[x]) return;
33 bel[x]=cnt;
34 ans+=val[mx[x]]*a[x];
35 chmin(mn,val[mx[x]]-val[sc[x]]);
36 if(mx[x]!=x)dfs(mx[x]);
37 }
38 signed main(){
39 freopen("goods.in","r",stdin);
40 freopen("goods.out","w",stdout);
41 n=read();
42 for(int i=1;i<=n;i++)
43 f[i]=read(), c[i]=read(), d[i]=read(), a[i]=read();
44 for(int i=1;i<=n;i++){
45 val[i]=d[f[i]]-c[i];
46 if(val[i]>val[mx[f[i]]]) sc[f[i]]=mx[f[i]], mx[f[i]]=i;
47 else if(val[i]>val[sc[f[i]]]) sc[f[i]]=i;
48 }
49 for(int i=1;i<=n;i++)
50 if(!bel[i]) ++cnt,mn=INT_MAX,dfs(i);
51 write(ans,'\n');
52 return 0;
53 }

T1

T2 ZYB玩字符串


可以想到暴力枚举子串暴力删除$check$,但假了,因为删除顺序可能导致结果不同。

考虑$DP$来$check$。设$f_{l,r}$表示母串$s$内$l$到$r$区间内的串能否被选出的子串$p$匹配。如果$r-l+1$不是$|p|$的倍数,那么要求剩余部分拼成$p$的前缀。

有转移:

$f_{l,r}|=f_{l,r-1}\text{&}[s_r=q_{(l-r)\textit{ mod }|p|+1}]$

$f_{l,r}|=f_{l,r-k\times |p|}\text{&}f_{t-k\times |p|+1,r}$

可以用字符集出现次数的$gcd$剪枝,跑得很快(其实还能记忆化,会更快

$code:$

  1 #include<bits/stdc++.h>
2 using namespace std;
3
4 namespace IO{
5 inline int read(){
6 char ch=getchar(); int x=0,f=1;
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 inline void write(int x,char sp){
12 char ch[20]; int len=0;
13 if(x<0){ putchar('-'); x=~x+1; }
14 do{ ch[len++]=x%10+(1<<4)+(1<<5); x/=10; }while(x);
15 for(int i=len-1;~i;--i) putchar(ch[i]); putchar(sp);
16 }
17 inline int max(int x,int y){ return x<y?y:x; }
18 inline int min(int x,int y){ return x<y?x:y; }
19 inline void swap(int &x,int &y){ x^=y^=x^=y; }
20 inline void chmax(int &x,int y){ x=x<y?y:x; }
21 inline void chmin(int &x,int y){ x=x<y?x:y; }
22 } using namespace IO;
23
24 const int NN=210;
25 int T,n,g,hh,res,sah[30],has[30],apr[30],tms[30],f[NN][NN];
26 char s[NN],tmp[NN],ans[NN];
27 inline int gcd(int a,int b){ return !b?a:gcd(b,a%b); }
28
29 void init(){
30 hh=0; res=INT_MAX; ans[1]='z'+1;
31 memset(apr,0,sizeof(apr)); memset(has,0,sizeof(has));
32 for(int i=1;i<=n;i++){
33 if(!has[s[i]-'a']) has[s[i]-'a']=++hh, sah[hh]=s[i]-'a';
34 ++apr[has[s[i]-'a']];
35 }
36 g=gcd(apr[1],apr[2]);
37 for(int i=3;i<=hh;i++) g=gcd(g,apr[i]);
38 for(int i=1;i<=hh;i++) tms[i]=apr[i]/g;
39 }
40 bool begin(int l,int r){
41 if(n%(r-l+1)) return 0;
42 memset(apr,0,sizeof(apr));
43 for(int i=l;i<=r;i++) ++apr[has[s[i]-'a']];
44 for(int i=1;i<=hh;i++){
45 if(!apr[i]) return 0;
46 if(i>1&&apr[i]/tms[i]!=apr[i-1]/tms[i-1]) return 0;
47 }
48 return 1;
49 }
50 void upd(int l,int r){
51 int len=r-l+1;
52 for(int i=l;i<=r;i++) tmp[i-l+1]=s[i];
53 if(len<res){
54 res=len;
55 for(int i=1;i<=len;i++) ans[i]=tmp[i];
56 return;
57 }
58 if(len>res) return;
59 for(int i=1;i<=len;i++){
60 if(tmp[i]>ans[i]) return;
61 if(tmp[i]<ans[i]){
62 for(int j=1;j<=len;j++) ans[i]=tmp[i];
63 return;
64 }
65 }
66 }
67 bool check(int l,int r){
68 memset(f,0,sizeof(f));
69 int len=r-l+1; f[l][r]=1;
70 for(int i=l;i<=r;i++) tmp[i-l+1]=s[i];
71 for(int i=1;i<=n-len+1;i++)
72 if(s[i]==tmp[1]) f[i][i]=1;
73 for(int i=2;i<=n;i++)
74 for(int j=1;j<=n-i+1;j++){
75 int x=j,y=j+i-1,ne=(i-1)%len+1;
76 f[x][y]|=f[x][y-1]&(s[y]==tmp[ne]);
77 for(int k=len;k<i;k+=len)
78 f[x][y]|=f[x][y-k]&f[y-k+1][y];
79 }
80 return f[1][n];
81 }
82
83 signed main(){
84 freopen("string.in","r",stdin);
85 freopen("string.out","w",stdout);
86 T=read();
87 while(T--){
88 scanf("%s",s+1); n=strlen(s+1);
89 init();
90 for(int i=1;i<=n;i++){
91 if(res!=INT_MAX) break;
92 for(int j=i;j<=n;j++){
93 if(!begin(j-i+1,j)) continue;
94 if(check(j-i+1,j)) upd(j-i+1,j);
95 }
96 }
97 for(int i=1;i<=res;i++) putchar(ans[i]);putchar('\n');
98 }
99 return 0;
100 }

T2

T3 午餐


神仙题,参考$DC$学长博客,讲得超清楚

$code:$

 1 #include<bits/stdc++.h>
2 #define x first
3 #define y second
4 #define mp make_pair
5 using namespace std;
6 typedef pair<int,int> pii;
7
8 namespace IO{
9 inline int read(){
10 char ch=getchar(); int x=0,f=1;
11 while(ch<'0'||ch>'9'){ if(ch=='-') f=-1; ch=getchar(); }
12 while(ch>='0'&&ch<='9'){ x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
13 return x*f;
14 }
15 inline void write(int x,char sp){
16 char ch[20]; int len=0;
17 if(x<0){ putchar('-'); x=~x+1; }
18 do{ ch[len++]=x%10+(1<<4)+(1<<5); x/=10; }while(x);
19 for(int i=len-1;~i;--i) putchar(ch[i]); putchar(sp);
20 }
21 inline int max(int x,int y){ return x<y?y:x; }
22 inline int min(int x,int y){ return x<y?x:y; }
23 inline void swap(int &x,int &y){ x^=y^=x^=y; }
24 inline void chmax(int &x,int y){ x=x<y?y:x; }
25 inline void chmin(int &x,int y){ x=x<y?x:y; }
26 } using namespace IO;
27
28 const int NN=2e5+5,inf=0x3fffffff;
29 int n,m,u[NN],v[NN],L[NN],R[NN],is[NN],h[NN],f[NN];
30 int idx,to[NN<<1],nex[NN<<1],head[NN],l[NN<<1],r[NN<<1];
31 inline void add(int a,int b,int c,int d){
32 to[++idx]=b; nex[idx]=head[a]; head[a]=idx; l[idx]=c; r[idx]=d;
33 to[++idx]=a; nex[idx]=head[b]; head[b]=idx; l[idx]=c; r[idx]=d;
34 }
35
36 void dij(){
37 priority_queue<pii,vector<pii>,greater<pii> >q;
38 for(int i=1;i<=n;i++)
39 if(is[i]==-1){
40 h[i]=inf;
41 q.push(mp(inf,i));
42 }
43 while(!q.empty()){
44 int x=q.top().y,y=q.top().x;
45 q.pop();
46 for(int i=head[x];i;i=nex[i]){
47 int vv=to[i];
48 if(h[x]>=r[i]&&h[vv]<l[i]){
49 h[vv]=l[i];
50 q.push(mp(h[vv],vv));
51 }
52 }
53 }
54 priority_queue<pii >qq; qq.push(mp(0,1));
55 for(int i=2;i<=n;i++) f[i]=inf;
56 while(!qq.empty()){
57 int x=qq.top().y,y=qq.top().x;
58 qq.pop();
59 for(int i=head[x];i;i=nex[i]){
60 int vv=to[i],val=max(h[vv]+1,max(f[x],l[i]));
61 if(f[vv]>val&&val<=r[i]){
62 f[vv]=val;
63 qq.push(mp(f[vv],vv));
64 }
65 }
66 }
67 }
68
69 signed main(){
70 freopen("lunch.in","r",stdin);
71 freopen("lunch.out","w",stdout);
72 n=read(); m=read();
73 for(int i=1;i<=m;i++){
74 u[i]=read(),v[i]=read(),L[i]=read(),R[i]=read();
75 add(u[i],v[i],L[i],R[i]);
76 }
77 for(int i=1;i<=n;i++) is[i]=read();
78 dij();
79 if(h[1]){ puts("Impossible"); return 0; }
80 for(int i=1;i<=n;i++) if(is[i]==1&&f[i]==inf){ puts("Impossible"); return 0; }
81 for(int i=1;i<=m;i++)
82 if(f[u[i]]<=R[i]&&f[v[i]]<=R[i]) chmax(L[i],max(f[u[i]],f[v[i]]));
83 for(int i=1;i<=m;i++) write(L[i],'\n');
84 return 0;
85 }

T4

T4 计数


前序遍历中编号满足$a<b$,只有两种情况:

$1$.$a$是$b$的祖先

$2$.$a$在$LCA$的左子树,$b$在$LCA$的右子树。

考虑加限制,强制令前序遍历中$a<b$,那么中序遍历中:

$1$.$a$在$b$前,那么$b$只能在$a$的右子树或是上面第二种情况,可以总结为$b$不在$a$

$2$.$a$在$b$后,那么$b$只能在$a$的左子树中。

两种限制对$a$的左子树大小都有要求,$1$要求大小小于$b-a$,$2$要求大小不小于$b-a$。

于是可以求出$a$左子树大小范围,考虑$DP$。

$f_{i,j}$表示$i$子树大小为$j$的方案,有:

$f_{i,j}=\sum_kf_{i+1,k}\times f_{i+k+1,i-k-1}$,$k$为$i$可行的左子树大小。

$code:$

 1 #include<bits/stdc++.h>
2 #define int long long
3 using namespace std;
4
5 namespace IO{
6 inline int read(){
7 char ch=getchar(); int x=0,f=1;
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 inline void write(int x,char sp){
13 char ch[20]; int len=0;
14 if(x<0){ putchar('-'); x=~x+1; }
15 do{ ch[len++]=x%10+(1<<4)+(1<<5); x/=10; }while(x);
16 for(int i=len-1;~i;--i) putchar(ch[i]); putchar(sp);
17 }
18 inline int max(int x,int y){ return x<y?y:x; }
19 inline int min(int x,int y){ return x<y?x:y; }
20 inline void swap(int &x,int &y){ x^=y^=x^=y; }
21 inline void chmax(int &x,int y){ x=x<y?y:x; }
22 inline void chmin(int &x,int y){ x=x<y?x:y; }
23 } using namespace IO;
24
25 const int NN=405,p=1e9+7;
26 int t,n,m,u,v,l[NN],r[NN],f[NN][NN];
27
28 int dfs(int pos,int num){
29 if(f[pos][num]!=-1) return f[pos][num];
30 if(pos>n||!num) return f[pos][num]=1;
31 if(num>n-pos+1||num<l[pos]) return f[pos][num]=0;
32 int up=min(num-1,r[pos]); f[pos][num]=0;
33 for(int i=l[pos];i<=up;i++)
34 (f[pos][num]+=dfs(pos+1,i)*dfs(pos+i+1,num-i-1)%p)%=p;
35 return f[pos][num];
36 }
37
38 signed main(){
39 // freopen("count.in","r",stdin);
40 // freopen("count.out","w",stdout);
41 t=read();
42 while(t--){
43 n=read(); m=read();
44 memset(f,-1,sizeof(f));
45 for(int i=1;i<=n;i++)
46 l[i]=0, r[i]=n-i;
47 for(int i=1;i<=m;i++){
48 u=read(), v=read();
49 if(u<v) chmin(r[u],v-u-1);
50 else chmax(l[v],u-v);
51 }
52 write(dfs(1,n),'\n');
53 }
54 return 0;
55 }

T4

2021.9.14考试总结[NOIP模拟53]的更多相关文章

  1. 2021.8.14考试总结[NOIP模拟39]

    T1 打地鼠 全场就俩人没切,还有一个是忘关$freopen$了. $code:$ 1 #include<bits/stdc++.h> 2 #define rin register sig ...

  2. 2021.9.17考试总结[NOIP模拟55]

    有的考试表面上自称NOIP模拟,背地里却是绍兴一中NOI模拟 吓得我直接文件打错 T1 Skip 设状态$f_i$为最后一次选$i$在$i$时的最优解.有$f_i=max_{j<i}[f_j+a ...

  3. 2021.9.13考试总结[NOIP模拟52]

    T1 路径 考虑每一位的贡献,第$i$位每$2^i$个数会变一次,那么答案为$\sum_{i=1}^{log_2n} \frac{n}{2^i}$. $code:$ 1 #include<bit ...

  4. 2021.8.11考试总结[NOIP模拟36]

    T1 Dove玩扑克 考场并查集加树状数组加桶期望$65pts$实际$80pts$,考后多开个数组记哪些数出现过,只扫出现过的数就切了.用$set$维护可以把被删没的数去掉,更快. $code:$ 1 ...

  5. 2021.7.29考试总结[NOIP模拟27]

    T1 牛半仙的妹子图 做法挺多的,可以最小生成树或者最短路,复杂度O(cq),c是颜色数. 我考场上想到了原来做过的一道题影子,就用了并查集,把边权排序后一个个插入,记录权值的前缀和,复杂度mlogm ...

  6. 2021.7.15考试总结[NOIP模拟16]

    ZJ模拟D2就是NB.. T1 Star Way To Heaven 谁能想到这竟是个最小生成树呢?(T1挂分100的高人JYF就在我身边 把上边界和下边界看成一个点和星星跑最小生成树,从上边界开始跑 ...

  7. 2021.9.12考试总结[NOIP模拟51]

    T1 茅山道术 仔细观察发现对于每个点只考虑它前面第一个与它颜色相同的点即可. 又仔细观察发现对一段区间染色后以这个区间内点为端点的区间不能染色. 于是对区间右端点而言,区间染色的贡献为遍历到区间左端 ...

  8. 2021.9.9考试总结[NOIP模拟50]

    T1 第零题 神秘结论:从一个点满体力到另一个点的复活次数与倒过来相同. 于是预处理出每个点向上走第$2^i$个死亡点的位置,具体实现可以倍增或二分. 每次询问先从两个点同时向上倍增,都转到离$LCA ...

  9. 2021.9.7考试总结[NOIP模拟49]

    T1 Reverse $BFS$暴力$O(n^2)$ 过程中重复枚举了很多点,考虑用链表记录当前点后面可到达的第一个未更新点. 搜索时枚举翻转子串的左端点,之后便可以算出翻转后$1$的位置. $cod ...

随机推荐

  1. Sentry 后端监控 - 最佳实践(官方教程)

    系列 1 分钟快速使用 Docker 上手最新版 Sentry-CLI - 创建版本 快速使用 Docker 上手 Sentry-CLI - 30 秒上手 Source Maps Sentry For ...

  2. freeswitch刷新网关方法

    1.freeswitch xml配置文件新增网关后,使其生效,可以重启freeswitch或者使用命令方式 fs_cli -H 127.0.0.1 -P 8021 -p hmzj -x sofia p ...

  3. 记录一次C语言中free(p)失败

    首先介绍一下自己的程序出错的原因,然后总结一下什么时候free会失败. 1.程序伪代码 // 已知payload已经指向一部分内存数据 char * payload; int payload_len; ...

  4. HDU 6170 FFF at Valentine(强联通缩点+拓扑排序)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6165 题意:给你一个无环,无重边的有向图,问你任意两点,是否存在路径使得其中一点能到达另一点 解析:强 ...

  5. PHP中的输出缓冲控制

    在 PHP 中,我们直接进行 echo . 或者 print_r 的时候,输出的内容就会直接打印出来.但是,在某些情况下,我们并不想直接打印,这个时候就可以使用输出缓冲控制来进行输出打印的控制.当然, ...

  6. PHP匿名类的用法

    在PHP7之后,PHP中加入了匿名类的特性.匿名类和匿名方法让PHP成为了更现代化的语言,也让我们的代码开发工作越来越方便.我们先来看看匿名类的简单使用. // 直接定义 $objA = new cl ...

  7. mysql5.7当两个字段名类似,查询时会出错

    excepInfo: select id,describe from iwebshop_student_problem where id=256 order by id desc -- You hav ...

  8. Orchar Core 创建一个模块化的ASP.NET Core应用程序

    您将构建什么?您将构建一个模块化的ASP.NET Core MVC Web应用程序,类似于Orchard Core附带的示例"Hello World"应用程序.它包括一个Web应用 ...

  9. 记一次k8s pod频繁重启的优化之旅

    关键词:k8s.jvm.高可用 1.背景 最近有运维反馈某个微服务频繁重启,客户映像特别不好,需要我们尽快看一下. 听他说完我立马到监控平台去看这个服务的运行情况,确实重启了很多次.对于技术人员来说, ...

  10. jQuery has been removed

    jQuery has been removed, 新的项目不要用jQuery了 这些问题都已经有了解决方案 * $()选择器, * $.ajax, * $dom.on("click" ...