8.12 纪中集训 Day12
T1少女觉
Description
在幽暗的地灵殿中,居住着一位少女,名为古明地觉。
据说,从来没有人敢踏入过那座地灵殿,因为人们恐惧于觉一族拥有的能力——读心。
掌控人心者,可控天下。
咳咳。
人的记忆可以被描述为一个黑块(B)与白块(W)的序列,其中情感值被定义为序列中黑块数量与白块数量之比。
小五口在发动读心术时,首先要解析人的记忆序列,因此,需要将序列分割为一些段,并且要求每一段记忆序列的情感值都相等。
下面给出两个例子:
BWWWBB -> BW + WWBB (Ratio=1:1)
WWWBBBWWWWWWWWWB -> WWWB + BBWWWWWW + WWWB (Ratio=3:1)
现在小五手上有一个人的记忆序列,她想要知道,如何将手中的记忆序列分成尽可能多的段呢?
据说,从来没有人敢踏入过那座地灵殿,因为人们恐惧于觉一族拥有的能力——读心。
掌控人心者,可控天下。
咳咳。
人的记忆可以被描述为一个黑块(B)与白块(W)的序列,其中情感值被定义为序列中黑块数量与白块数量之比。
小五口在发动读心术时,首先要解析人的记忆序列,因此,需要将序列分割为一些段,并且要求每一段记忆序列的情感值都相等。
下面给出两个例子:
BWWWBB -> BW + WWBB (Ratio=1:1)
WWWBBBWWWWWWWWWB -> WWWB + BBWWWWWW + WWWB (Ratio=3:1)
现在小五手上有一个人的记忆序列,她想要知道,如何将手中的记忆序列分成尽可能多的段呢?
Input
第一行包含一个正整数T,代表数据组数。
对于每一组测试数据,第一行包含一个正整数N。
接下来N行描述一个序列,每行包含一个正整数K和一个大写字母C,表示序列接下来有连续K个颜色为C的方块。
对于每一组测试数据,第一行包含一个正整数N。
接下来N行描述一个序列,每行包含一个正整数K和一个大写字母C,表示序列接下来有连续K个颜色为C的方块。
Output
对于每组测试数据输出一行一个正整数,表示最多分成的段数。
Sample Input
3
3
1 B
3 W
2 B
4
3 W
3 B
9 W
1 B
2
2 W
3 W
Sample Output
2
3
5
Data Constraint
对于10%的数据,n<=15
对于20%的数据,n<=500
另有30%的数据,K=1
另有30%的数据,K<=50
对于100%的数据,N<=10^5,序列长度不超过10^9
保证对于全部测试点,输入文件行数不超过2.5*10^6
对于20%的数据,n<=500
另有30%的数据,K=1
另有30%的数据,K<=50
对于100%的数据,N<=10^5,序列长度不超过10^9
保证对于全部测试点,输入文件行数不超过2.5*10^6
考场思路/正解
贪心,每组数据的黑白比例一定是固定的,我们只要从左到右扫过去,符合这个比值就ans++,然后就愉快都解决了。
不过考场上我忘记开long long ,所以没有A
Code
#include<cstdio> #include<algorithm> #define LL long long #define NAME "silly" using namespace std; LL T,n,k[100010],slw,slb,s1,s2,ans; char s[100010][2]; void Open()<%freopen(NAME".in","r",stdin);freopen(NAME".out","w",stdout);%> int main() { Open(); scanf("%lld",&T); while(T--) { scanf("%lld",&n); ans=0,slb=0,slw=0; for(int i=1;i<=n;i++) { scanf("%lld%s",&k[i],s[i]); if(s[i][0]=='B') slb+=k[i]; else slw+=k[i]; } if(slb==0) { printf("%lld\n",slw); continue; } if(slw==0) { printf("%lld\n",slb); continue; } s1=0,s2=0; for(int i=1;i<=n;i++) { if(s[i][0]=='B') { if((s1*slb)%slw!=0) { s2+=k[i]; continue; } if(s2<s1*slb/slw && s1*slb/slw<=s2+k[i]) ans++; s2+=k[i]; } else { if((s2*slw)%slb!=0) { s1+=k[i]; continue; } if(s1<s2*slw/slb && s2*slw/slb<=s1+k[i]) ans++; s1+=k[i]; } } printf("%lld\n",ans); } return 0; }
T2灵知的太阳信仰
Description
在炽热的核熔炉中,居住着一位少女,名为灵乌路空。
据说,从来没有人敢踏入过那个熔炉,因为人们畏缩于空所持有的力量——核能。
核焰,可融真金。
咳咳。
每次核融的时候,空都会选取一些原子,排成一列。然后,她会将原子序列分成一些段,并将每段进行一次核融。
一个原子有两个属性:质子数和中子数。
每一段需要满足以下条件:
1、同种元素会发生相互排斥,因此,同一段中不能存在两个质子数相同的原子。
2、核融时,空需要对一段原子加以防护,防护罩的数值等于这段中最大的中子数。换句话说,如果这段原子的中子数最大为x,那么空需要付出x的代价建立防护罩。求核融整个原子序列的最小代价和。
据说,从来没有人敢踏入过那个熔炉,因为人们畏缩于空所持有的力量——核能。
核焰,可融真金。
咳咳。
每次核融的时候,空都会选取一些原子,排成一列。然后,她会将原子序列分成一些段,并将每段进行一次核融。
一个原子有两个属性:质子数和中子数。
每一段需要满足以下条件:
1、同种元素会发生相互排斥,因此,同一段中不能存在两个质子数相同的原子。
2、核融时,空需要对一段原子加以防护,防护罩的数值等于这段中最大的中子数。换句话说,如果这段原子的中子数最大为x,那么空需要付出x的代价建立防护罩。求核融整个原子序列的最小代价和。
Input
第一行一个正整数N,表示原子的个数。
接下来N行,每行两个正整数pi和ni,表示第i个原子的质子数和中子数。
接下来N行,每行两个正整数pi和ni,表示第i个原子的质子数和中子数。
Output
输出一行一个整数,表示最小代价和。
Sample Input
5
3 11
2 13
1 12
2 9
3 13
Sample Output
26
Data Constraint
对于20%的数据,1<=n<=100
对于40%的数据,1<=n<=1000
对于100%的数据,1<=n<=10^5,1<=pi<=n,1<=ni<=2*10^4
对于40%的数据,1<=n<=1000
对于100%的数据,1<=n<=10^5,1<=pi<=n,1<=ni<=2*10^4
考场思路
本来以为是一道非常简单的区间DP题,结果愣是没有做出来。
正解
好像就是区间DP,不过要用单调栈和set来优化罢了(改了一晚上)
Code
#include<cstdio> #include<algorithm> #include<cstring> #include<set> #define NAME "array" using namespace std; int n,L=1,R; int u[100010],v[100010],l[100010],book[20020],q[100010],p[100010],f[100010]; multiset<int> zx; void Open()<%freopen(NAME".in","r",stdin);freopen(NAME".out","w",stdout);%> int main() { Open(); scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d%d",&u[i],&v[i]); l[i]=max(l[i-1],book[u[i]]+1); book[u[i]]=i; } memset(f,0x3f,sizeof f); f[0]=0; for(int i=1;i<=n;i++) { while(L<=R && q[L]<l[i]) zx.erase(p[L]),L++; while(L<=R && v[q[R]]<v[i]) zx.erase(p[R]),R--; q[++R]=i; p[R]=f[q[R-1]]+v[i]; zx.insert(p[R]); zx.erase(p[L]); zx.insert(p[L]=f[l[i]-1]+v[q[L]]); f[i]=*zx.begin(); } printf("%d",f[n]); return 0; }
T3多段线性函数
Description
Input
Output
输出文件名为linear.out。
输出一行两个自然数,用空格隔开,依次为L和R。
输出一行两个自然数,用空格隔开,依次为L和R。
Sample Input
5
1 3
2 3
3 5
5 5
6 7
Sample Output
3 5
Data Constraint
正解
有点玄学,(其实好像可以用数学证明,只不过我不会,改日心情好时再来证吧!)
Code
#include<cstdio> #include<algorithm> #define NAME "linear" using namespace std; int n; int sz[200020]; void Open()<%freopen(NAME".in","r",stdin);freopen(NAME".out","w",stdout);%> int main() { Open(); scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d%d",&sz[i],&sz[i+n]); sort(sz+1,sz+1+2*n); printf("%d %d",sz[n],sz[n+1]); return 0; }
T4DY引擎
Description
BOSS送给小唐一辆车。小唐开着这辆车从PKU出发去ZJU上课了。
众所周知,天朝公路的收费站超多的。经过观察地图,小唐发现从PKU出发到ZJU的所有路径只会有N(2<=N<=300)个不同的中转点,其中有M(max(0, N-100) <=M<=N)个点是天朝的收费站。N个中转点标号为1…N,其中1代表PKU,N代表ZJU。中转点之间总共有E(E<=50,000)条双向边连接。
每个点还有一个附加属性,用0/1标记,0代表普通中转点,1代表收费站。当然,天朝的地图上面是不会直接告诉你第i个点是普通中转点还是收费站的。地图上有P(1<=P<=3,000)个提示,用[u, v, t]表示:[u, v]区间的所有中转点中,至少有t个收费站。数据保证由所有提示得到的每个点的属性是唯一的。
车既然是BOSS送的,自然非比寻常了。车子使用了世界上最先进的DaxiaYayamao引擎,简称DY引擎。DY引擎可以让车子从U瞬间转移到V,只要U和V的距离不超过L(1<=L<=1,000,000),并且U和V之间不能有收费站(小唐良民一枚,所以要是经过收费站就会停下来交完钱再走)。
DY引擎果然是好东西,但是可惜引擎最多只能用K(0<=K<=30)次。
众所周知,天朝公路的收费站超多的。经过观察地图,小唐发现从PKU出发到ZJU的所有路径只会有N(2<=N<=300)个不同的中转点,其中有M(max(0, N-100) <=M<=N)个点是天朝的收费站。N个中转点标号为1…N,其中1代表PKU,N代表ZJU。中转点之间总共有E(E<=50,000)条双向边连接。
每个点还有一个附加属性,用0/1标记,0代表普通中转点,1代表收费站。当然,天朝的地图上面是不会直接告诉你第i个点是普通中转点还是收费站的。地图上有P(1<=P<=3,000)个提示,用[u, v, t]表示:[u, v]区间的所有中转点中,至少有t个收费站。数据保证由所有提示得到的每个点的属性是唯一的。
车既然是BOSS送的,自然非比寻常了。车子使用了世界上最先进的DaxiaYayamao引擎,简称DY引擎。DY引擎可以让车子从U瞬间转移到V,只要U和V的距离不超过L(1<=L<=1,000,000),并且U和V之间不能有收费站(小唐良民一枚,所以要是经过收费站就会停下来交完钱再走)。
DY引擎果然是好东西,但是可惜引擎最多只能用K(0<=K<=30)次。
Input
第一行有6个整数N,M,E,P,L,K分别代表:N个中转点,M个收费站,E条边,P个提示,DY引擎的有效距离L,DY引擎的使用次数K。
接下去E行,每行有3个整数u,v,w(1<=u, v<=N; 1<=w<=1,000,000)表示:u和v之间有一条长度为w的双向边。
接下去P行,每行有3个整数u,v,t(1<=u<=v<=N; 0<=t<=u-v+1)表示: [u, v] 标号区间至少有t个收费站。
接下去E行,每行有3个整数u,v,w(1<=u, v<=N; 1<=w<=1,000,000)表示:u和v之间有一条长度为w的双向边。
接下去P行,每行有3个整数u,v,t(1<=u<=v<=N; 0<=t<=u-v+1)表示: [u, v] 标号区间至少有t个收费站。
Output
输出一个整数,表示小唐从PZU开到ZJU用的最短距离(瞬间转移距离当然是按0来计算的)。
Sample Input
6 2 6 2 5 1 1 2 1 2 3 2 3 6 3 1 4 1 4 5 2 5 6 3 2 5 2 4 6 2
Sample Output
1 【样例解释】 4、5是收费站。1->2(1)->6(1)
Data Constraint
对于30%的数据保证:
2<=N<=30,max(0, N-10) <=M<=N,0<=k<=10
对于100%的数据保证:
2<=N<=300,max(0, N-100) <=M<=N,E<=50,000,1<=P<=3,000,1<=L<=1,000,000,0<=K<=30
2<=N<=30,max(0, N-10) <=M<=N,0<=k<=10
对于100%的数据保证:
2<=N<=300,max(0, N-100) <=M<=N,E<=50,000,1<=P<=3,000,1<=L<=1,000,000,0<=K<=30
考场思路
空白
正解
有空探索呀
总结
Fighting!