2018BNU校赛总决赛

题解是qls的题解我就懒得写了23333


 

A塞特斯玛斯塔

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld

题目描述 

quailty是一名狂热的ACM音游选手,沉迷各种音乐游戏,比如Lunatic Rave 2,osu!之类的。

今天,quailty玩的是国内游戏厂商雷亚(并不是赞助商)出品的一款音乐游戏Cytus。

游戏中,玩家需要随着游戏界面中上下移动的扫描线来适时演奏对应音符。

当上下移动的黑色线(扫描线)与圆形的物体(音符)的圆心重合时点击音符。

普通音符(图中第一种)只需点击即可。

锁链音符(图中第二种)将带箭头的音符(滑块)按下后不要松开,并将滑块沿着斜线和圆点组成的路径拖动,直至拖动到最后一个圆点处方可松开。注意拖动过程中应保持滑块圆心始终与扫描线重合。

长按音符(图中第三种)按下后不要松开,原地不动,等扫描线到达其末端并显示判定结果后方可松开。

Cytus共有五种判定,从好到坏依次为:彩PERFECT、黑PERFECT、GOOD、BAD、MISS。

得分中包括了90%的“判定分”和10%的“连击分”,而连击分是累进计算的,断COMBO对其影响很大,往往只要有1个MISS就会损失几万的连击分。

彩PERFECT和黑PERFECT在计算得分时一视同仁,只要全部PERFECT即可获得满分,满分为1000000,被称为MILLION Master。

quailty真的很严格,如果打完一把没有拿到MILLION Master,他就认为自己是NAIVE Noob。

现在给你quailty打出的判定序列,请你输出这次游戏的评价是MILLION Master还是NAIVE Noob。


输入描述:

第一行是一个正整数T ( 1 ≤ T ≤ 5 ),表示测试数据的组数,
每组测试数据,第一行是一个正整数n ( 1 ≤ n ≤ 100000 ),表示该组测试数据包含的判定数。接下来的n行,每行包含"PERFECT"、"GOOD"、"BAD"、"MISS"之中的一个字符串,表示quailty打出的一个判定。

输出描述:

对于每组数据,输出一行,包含一个字符串,表示这次游戏的评价。
示例1

输入

2
5
PERFECT
PERFECT
PERFECT
PERFECT
PERFECT
10
PERFECT
MISS
PERFECT
BAD
BAD
GOOD
BAD
GOOD
GOOD
MISS

输出

MILLION Master
NAIVE Noob

判断是不是全是perfect。

 1 #include<bits/stdc++.h>
 2 #define clr(x) memset(x,0,sizeof(x))
 3 #define clr_1(x) memset(x,-1,sizeof(x))
 4 #define mod 1000000007
 5 #define LL long long
 6 #define INF 0x3f3f3f3f
 7 #define mp(x,y) make_pair(x,y)
 8 using namespace std;
 9 const int N=1e5+10;
10 int n,m,flag,T;
11 char s[N],ans[]="PERFECT";
12 int main()
13 {
14     scanf("%d",&T);
15     while(T--)
16     {
17         scanf("%d",&n);
18         flag=1;
19         for(int i=1;i<=n;i++)
20         {
21             scanf("%s",s);
22             if(strcmp(s,ans)!=0)
23                 flag=0;
24         }
25         if(flag)
26             printf("MILLION Master\n");
27         else
28             printf("NAIVE Noob\n");
29     }
30     return 0;
31 }
View Code

 

B 外挂使用拒绝

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld

题目描述

ATG5是ATG系列最新作,游戏故事发生以美国洛杉矶及其周边地区为原型的城市Sos Lantos,是现实地区中的洛杉矶和南加州。制作单位拍摄了超过25万张相关照片,并且研究了人口调查和汽车销售数据,以建立游戏中的世界。

ATG系列历来都是以黑帮生活为背景的知名动作冒险游戏。主人公自然与黑道脱不了干系,在ATG5中游戏元素将会得到增强,加入了更加开放自由的世界,以故事驱动,以任务为准的游戏玩法和多人模式。故事主题聚焦金钱永不眠的南加利福尼亚。这次作品是有史以来最具活力的和最多元化的开放式世界,作为玩家可以反复进入三个角色的生活,玩交织在一起的所有内容。

ATG5这款游戏质量很高,但是外挂猖獗。。。

最近,三七开发现了一款神奇的外挂,可以让他在多个账号之间转移金钱。

神奇外挂的神奇不止于此,当他把一个账号的金钱转移到另一个账户时,原来账户里的金钱并不会减少!是不是很神奇?

三七开一共有n个账号,每一天他都会通过这个神奇外挂把第1个账号的金钱“转移”到第2个账号,再把第2个账号的金钱“转移”到第3个账号,……,再把第n-1个账号的金钱“转移”到第n个账号。

但是三七开忘了一件事情,游戏中金钱数量是有上限的,每当一个账号的金钱数大于等于1000000007(=109+7)时,这个账号的金钱数就会对109+7取模,即变成金钱数除以109+7的余数。尽管如此,三七开还是很开心地继续使用着他的神奇外挂,并且没有花账号里的一分金钱。

然而,在三七开使用了k天神奇外挂之后,B星公司(ATG5的发行公司)发现了他的开挂行为。B星公司对使用外挂行为非常仁慈,决定不对三七开进行封号处理,而是将三七开的所有账号的金钱数恢复至他开挂以前的数值。但服务器并没有关于那么久远的数据的存档,只有现在的金钱数的数据,以及检测到的开挂天数k。

你能帮助B星公司恢复三七开的账号数据吗?

输入描述:

第一行是一个正整数T(T ≤ 15),表示测试数据的组数,

对于每组测试数据,

第一行包含两个整数n(2 ≤ n ≤ 1000),k(0 ≤ k ≤ 100000000),表示账号个数和开挂天数,

第二行包含n个小于109+7的非负整数,第i个整数表示当前第i个账号的金钱数。

输出描述:

对于每组测试数据,输出一行,包含n个以空格分隔的非负整数(每个数范围小于10
9
+7,注意不要有行末空格),第i个整数表示开挂前第i个账号的金钱数。
示例1

输入

2
3 1
3 2 1
4 2
1 2 1 2

输出

3 1000000006 1000000006
1 0 1000000005 2

连加和连减这一类的都可以从杨辉三角找找规律2333,找找规律就能出通项了。

 1 #include<bits/stdc++.h>
 2 #define clr(x) memset(x,0,sizeof(x))
 3 #define clr_1(x) memset(x,-1,sizeof(x))
 4 #define mod 1000000007
 5 #define LL long long
 6 #define INF 0x3f3f3f3f
 7 #define mp(x,y) make_pair(x,y)
 8 using namespace std;
 9 const int N=1e3+10;
10 LL a[N];
11 LL fac[N],inv[N];
12 LL ans[N],k;
13 int T,n,m,tk;
14 LL quickpow(LL x,LL n)
15 {
16     LL ans=1;
17     x%=mod;
18     while(n)
19     {
20         if(n&1) ans=ans*x%mod;
21         n>>=1;
22         x=x*x%mod;
23     }
24     return ans;
25 }
26 void init(int n,LL k)
27 {
28     fac[0]=1;
29     LL p=1;
30     for(int i=1;i<=n && k>=0;i++,k--)
31         fac[i]=fac[i-1]*k%mod;
32     for(int i=1;i<=n;i++)
33         p=p*i%mod;
34     inv[n]=quickpow(p,mod-2);
35     for(int i=n-1;i>=0;i--)
36         inv[i]=inv[i+1]*(i+1)%mod;
37     return ;
38 }
39 LL comb(LL k,int n)
40 {
41     if(1LL*n>k)
42         return 0;
43     else
44         return (fac[n]*inv[n])%mod;
45 }
46 int main()
47 {
48     scanf("%d",&T);
49     while(T--)
50     {
51         scanf("%d%lld",&n,&k);
52         for(int i=1;i<=n;i++)
53             scanf("%lld",a+i);
54         init(n,k);
55         clr(ans);
56         for(int i=1;i<=n;i++)
57         {
58             tk=-1;
59             m=-1;
60             for(int j=i;j>=1;j--)
61             {
62                 tk++;
63                 m=-m;
64                 ans[i]=((ans[i]+comb(k,tk)*m%mod*a[j]%mod)%mod+mod)%mod;
65             }
66         }
67         for(int i=1;i<n;i++)
68             printf("%lld ",ans[i]);
69         printf("%lld\n",ans[n]);
70     }
71     return 0;
72 }
View Code

 

C 萌萌哒身高差

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
Special Judge, 64bit IO Format: %lld

题目描述

 

“清明时节雨纷纷,路上行人欲断魂。”

然而wfy同学的心情是愉快的,因为BNU ACM队出去春游啦!并且,嗯。。。

以下是wfy同学的日记:

昨天,何老师告诉我们:明天我们去春游,大家准备好喝的和吃的哦!
大家听了都兴奋起来,有的欢呼,有的鼓掌,开心得不得了。第二天,我们早早地来到学校,迫不及待地上了车,来到了公园。一进门,啊,太美了!公园中有那么多树,有高有矮,有粗有瘦,密密的,在春风吹拂下轻轻摇摆着,像是欢迎我们的到来。公园中有那么多的鲜花,有红有黄,有紫有白,散发着淡淡的清香,闻得我们都醉了。公园的边角上有一条清澈的小河,河水缓缓地流淌着,可以看到水里的鱼儿在快活地游来游去,多自在啊!水草碧绿碧绿的,多新鲜啊!小河的旁边是一片小树林,远远望去一片鲜绿。我们在里面吃东西、做游戏、捉迷藏,玩得疯极了。树林的后面是连绵起伏的小山坡,蜿蜿的真像一条游动的蛇。当然,我觉得公园的天空也很美。它万里无云,一碧如洗,很清澈。小鸟在展翅飞翔,它们形态各异,一会儿上升,一会儿下滑,一会儿吃虫,一会儿在小树林里休息,非常悠闲。快乐时光总是那么短暂,很快,天色就昏暗了。我们依依不舍地上了车,回到了学校,我真希望明年的春天还能再来看看这美丽的公园。
回到学校后,何老师说:请大家排成一排,我们来拍照片啦!
何老师特别喜欢萌的东西,比如**,比如****,等等。
何老师认为,同学们站成一排时,相邻两个同学身高相差越多,这两个同学站在一起越萌。
那么所有相邻两个同学的身高差加起来越大,拍出来的照片就越萌,也就是这张照片的萌力指数。
何老师希望拍出来的照片的萌力指数尽可能大。
然而何老师并不是数学老师,而是语文老师。何老师觉得很GG。
何老师只想知道,如果让同学们随便站成一排(站成所有排列的可能性都相等),萌力指数的数学期望是多少。
聪明的我一下子就算出了答案,然后何老师就奖励了我一个很萌的礼物。
今天真的好开心。

BNU ACM队共有n名同学,身高分别是,聪明的你能计算出何老师想要的数学期望吗?

输入描述:

第一个是一个正整数T(T ≤ 20),表示测试数据的组数,
每组测试数据只有一行,包含一个整数n(2 ≤ n ≤ 100)。

输出描述:

对于每组测试数据,输出一行,包含一个实数,表示萌力指数的数学期望值,要求相对误差不超过

也就是说,令输出结果为a,标准答案为b,若满足,则输出结果会被认为是正确答案。

示例1

输入

2
2
3

输出

1.000000000000
2.666666666667

说明

对于第二组样例,所有可能的排列是[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1],所以答案是
\frac{2+3+3+3+3+2}{6}=\frac{8}{3}
 

嗯找找规律写个第四第五项就可以发觉是 $ \frac{n^2-1}{3} $ 。别去推了,我推了半天还推错了orz。赛后推出来了太麻烦,不如猜公式。就是从上一个n-1的排列去推加进去一个n以后增加了多少,那么f[n]=[n-1]+一个计算n加进去后期望增加的贡献。可以通过固定右端的数字然枚举左端的数字来算,然后还有左端没有以及右端没有总共三种情况。概率就相当于出现总数除总排列数。

 1 #include<bits/stdc++.h>
 2 #define clr(x) memset(x,0,sizeof(x))
 3 #define clr_1(x) memset(x,-1,sizeof(x))
 4 #define mod 1000000007
 5 #define LL long long
 6 #define INF 0x3f3f3f3f
 7 #define mp(x,y) make_pair(x,y)
 8 using namespace std;
 9 const int N=1e2+10;
10 int T,n,m,all;
11 LL a[N],pre[N];
12 double ans[N];
13 void init(int n)
14 {
15     a[1]=1;
16     ans[1]=0;
17     for(int i=2;i<=n;i++)
18     {
19         a[i]=a[i-1]+2;
20         pre[i]=pre[i-1]+a[i];
21         ans[i]=1.0*pre[i]/3;
22     }
23     return ;
24 }
25 int main()
26 {
27     init(100);
28     scanf("%d",&T);
29     while(T--)
30     {
31         scanf("%d",&n);
32         printf("%.10f\n",ans[n]);
33     }
34     return 0;
35 }
View Code

 

D 雷电爆裂之力

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld

题目描述

听说导体切割磁感线可以发电?
 
今天,zhuaiballl想要做切割磁感线运动,感受雷电的力量。
 
南北方向有四条马路,从西到东依次是京师路,木铎路,金声路和新街口外大街,可以看成是四条平行的数轴,且相邻的两条数轴之间距离为1m。东西走向有许多小道连接了相邻的马路。假设地磁南极和地理北极重合,地磁北极和地理南极重合。现在zhuaiballl位于京师路的某个位置,想要出发前往新街口外大街,速度为1m/s。由于可能没有一条路径从西到东一直连向新街口外大街,所以每次遇到丁字路口时,zhuaiballl需要选择是往左走还是往右走,样例如下图所示。
 

 
zhuaiballl想要感受尽可能强的雷电力量,所以希望从他开始往东走时开始,到他到达新街口外大街所需要的时间尽可能短。
 
现在,给你附近的地图,你能否求出从zhuaiballl开始往东走时开始,到他到达新街口外大街的最短时间?

输入描述:

第一行是一个正整数T(≤ 20),表示测试数据的组数,

对于每组测试数据,

第一行是一个整数n,m,k(1≤ n,m,k ≤ 100000),分别表示连接京师路与木铎路,木铎路与金声路,金声路与新街口外大街的道路个数,

第二行包含n个以空格分隔的整数a1,a2,...,an,表示连接京师路与木铎路的各个小道的南北方向坐标(单位:m),

第三行包含m个以空格分隔的整数b1,b2,...,bm,表示连接木铎路与金声路的各个小道的南北方向坐标(单位:m),

第四行包含k个以空格分隔的整数c1,c2,...,ck,表示连接金声路与新街口外大街的各个小道的南北方向坐标(单位:m),

保证每行坐标按严格递增的顺序给出,并且坐标绝对值不超过109

输出描述:

对于每组测试数据,输出一行,包含一个整数,表示答案(单位:s)。
示例1

输入

1
3 3 2
-1 1 4
-3 2 4
-1 1

输出

5



序都给你排好了,你就枚举中间那条路的所有路位置,然后双指针指向前面和后面两边的路去做,O(n)的。

#include<bits/stdc++.h>
#define clr(x) memset(x,0,sizeof(x))
#define clr_1(x) memset(x,-1,sizeof(x))
#define LL long long
#define INF 0x3f3f3f3f
using namespace std;
const int N=1e5+10;
int n,m,k;
LL a[N],b[N],c[N];
int T,lt,rt;
LL ans,pt;
int main()
{
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d%d",&n,&m,&k);
        for(int i=1;i<=n;i++)
            scanf("%lld",a+i);
        for(int i=1;i<=m;i++)
            scanf("%lld",b+i);
        for(int i=1;i<=k;i++)
            scanf("%lld",c+i);
        ans=abs(a[1]-b[1])+abs(b[1]-c[1]);
        lt=rt=1;
        for(int i=1;i<=m;i++)
        {
            while(lt<n && a[lt]<b[i])
                lt++;
            while(rt<k && c[rt]<b[i])
                rt++;
            pt=0;
            if(lt>1)
                pt+=min(abs(a[lt]-b[i]),abs(a[lt-1]-b[i]));
            else
                pt+=abs(a[lt]-b[i]);
            if(rt>1)
                pt+=min(abs(c[rt]-b[i]),abs(c[rt-1]-b[i]));
            else
                pt+=abs(c[rt]-b[i]);
            ans=min(ans,pt);
        }
        printf("%lld\n",ans+3);
    }
    return 0;
}
View Code

 

E 可以来拯救吗

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld

题目描述

quailty is BNU's red sun.

quailty非常喜欢给同学讲题,一天,他又拉着SK给他讲题。

quailty:给一个长为n的序列,求给定子序列的和,会吗?

SK:。。

quailty:给一个长为n的序列,求给定子序列的和的平方,会吗?

SK:。。。

quailty:给一个长为n的序列,求所有子序列的和的平方和,会吗?

SK:。。。。。

quailty:给一个长为n的序列,求所有长为k的子序列的和的平方和,会吗?

SK:。。。。。。。。

quailty:给一个长为n的序列,求所有长为k的子序列的和的平方的异或和,会...

SK:我^(^&*((^%^#……

SK拔出了他的40m长刀,场面就快控制不住了,请你赶快来做出这道题,拯救一下quailty。

quailty is BNU's red sun.

输入描述:

第一行是一个正整数T(≤ 10),表示测试数据的组数,

对于每组测试数据,

第一行是两个正整数n,k(k ≤ n ≤ 100000),分别表示序列长度和需要考虑的子序列长度,

接下来一行包含n个不超过1000的正整数,表示序列的n个元素

为了简化问题,保证,也就是说,需要考虑的子序列不超过100000个。

输出描述:

对于每组测试数据,输出一行,包含一个整数,表示所有长为k的子序列的和的平方的异或和。
示例1

输入

1
4 2
1 2 3 4

输出

12

说明

对于样例,长度为2的子序列有[1,2],[1,3],[1,4],[2,3],[2,4],[3,4],所以答案是9^16^25^25^36^49=12(这里'^'是C++中的异或运算符)。


dfs暴力枚举所有会出现的序列,因为他保证考虑的序列不超过$ 10^6 $个。同时n最长为1000,所以没事的能过。要注意的是一旦 $ k> \frac{a}{2} $ 那么我们考虑的序列应该是 $ n-k $ 的序列,然后拿总和减掉这个序列和就行了。

 1 #include<bits/stdc++.h>
 2 #define clr(x) memset(x,0,sizeof(x))
 3 #define clr_1(x) memset(x,-1,sizeof(x))
 4 #define LL long long
 5 #define INF 0x3f3f3f3f
 6 using namespace std;
 7 const int N=1e5+10;
 8 LL a[N];
 9 int n,k,T;
10 bool rev;
11 LL all,ans;
12 void dfs(int pt,int now,LL sum)
13 {
14     if(now==k)
15     {
16         if(rev) ans^=(all-sum)*(all-sum);
17         else ans^=sum*sum;
18         return ;
19     }
20     if(n-pt+1<k-now) return ;
21     dfs(pt+1,now,sum);
22     dfs(pt+1,now+1,sum+a[pt]);
23     return ;
24 }
25 int main()
26 {
27     scanf("%d",&T);
28     while(T--)
29     {
30         scanf("%d%d",&n,&k);
31         all=0;
32         rev=0;
33         ans=0;
34         for(int i=1;i<=n;i++)
35         {
36              scanf("%lld",a+i);
37              all+=a[i];
38         }
39         if(k>n/2)
40         {
41             rev=1;
42             k=n-k;
43         }
44         dfs(1,0,0);
45         printf("%lld\n",ans);
46     }
47     return 0;
48 }
View Code

 

F 汤圆防漏理论

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld

题目描述

ghc很喜欢吃汤圆,但是汤圆很容易被粘(zhān)漏。

根据多年吃汤圆经验,ghc总结出了一套汤圆防漏理论:

互相接触的汤圆容易粘(zhān)在一起,并且接触面积不同,粘(zhān)在一起的粘(nián)度也不同。

当ghc要夹起一个汤圆时,这个汤圆和现在碗里与这个汤圆接触的所有汤圆之间的粘(nián)度的和,如果大于汤圆的硬度,这个汤圆就会被粘(zhān)漏。

今天ghc又要煮汤圆啦,今天要煮n个汤圆,并且摆盘的方法已经设计好:

汤圆按照编号,有m对汤圆互相接触,用xi, yi, zi表示编号为xi和yi的两个汤圆互相接触,粘(nián)度为zi

汤圆当然是越软越好吃,但是ghc的厨艺只允许把所有汤圆煮成同样的硬度。那么,汤圆的硬度最小可以是多少,可以满足吃的过程中,存在一种夹汤圆的顺序,使得没有汤圆会被粘(zhān)漏呢?

注意:

不考虑汤圆的重力作用;

不能同时夹多个汤圆;

吃完汤圆一定要喝点汤。

输入描述:

第一行是一个正整数T(≤ 5),表示测试数据的组数,

对于每组测试数据,

第一行是两个整数n,m(1≤ n,m≤ 100000),

接下来m行,每行包含三个整数xi, yi, zi(1≤ xi, yi ≤ n, xi ≠ yi, 1 ≤ zi ≤ 1000000),

同一对汤圆不会出现两次。

输出描述:

对于每组测试数据,输出一行,包含一个整数,表示汤圆硬度的最小值。
示例1

输入

1
4 6
1 2 2
1 3 2
1 4 2
2 3 3
2 4 3
3 4 5

输出

6



嗯代码我又写挫了。就是每次都贪心的找连边的比边权和最小的删掉。为了这个过程我写了一个记录位置的小根堆然后动态的加入删除。但是记录和维护堆的代码写出来很长的。。然后q巨的做法直接用set一堆代码就省了。

  1 #include<bits/stdc++.h>
  2 #define clr(x) memset(x,0,sizeof(x))
  3 #define clr_1(x) memset(x,-1,sizeof(x))
  4 #define mod 1000000007
  5 #define LL long long
  6 #define INF 0x3f3f3f3f
  7 #define mp(x,y) make_pair(x,y)
  8 using namespace std;
  9 const int N=2e5+10;
 10 struct edg
 11 {
 12     int next,to,val;
 13 }edge[N];
 14 int head[N],etot;
 15 void addedge(int u,int v,int val)
 16 {
 17     edge[++etot]=(edg){head[u],v,val};
 18     head[u]=etot;
 19     return ;
 20 }
 21 LL heap[N];
 22 int hashed[N],too[N];
 23 LL val[N],len,ans;
 24 int htot,u,v,ve,n,m,T;
 25 void init()
 26 {
 27     clr_1(head);
 28     etot=htot=0;
 29     clr(val);
 30 }
 31 void add(LL x,int pt)
 32 {
 33     heap[++htot]=x;
 34     hashed[htot]=pt;
 35     too[hashed[htot]]=htot;
 36     int p=htot;
 37     while(p>1 && heap[p]<heap[p>>1])
 38     {
 39         swap(too[hashed[p]],too[hashed[p>>1]]);
 40         swap(heap[p],heap[p>>1]);
 41         swap(hashed[p],hashed[p>>1]);
 42         p>>=1;
 43     }
 44     return ;
 45 }
 46 void pop()
 47 {
 48     swap(too[hashed[1]],too[hashed[htot]]);
 49     swap(heap[1],heap[htot]);
 50     swap(hashed[1],hashed[htot]);
 51     htot--;
 52     int p=1,maxpt;
 53     while(((p<<1)<=htot && heap[p]>heap[p<<1]) || ((p<<1|1)<=htot && heap[p]>heap[p<<1|1]))
 54     {
 55         if((p<<1|1)<=htot)
 56             maxpt=heap[p<<1]<heap[p<<1|1]?(p<<1):(p<<1|1);
 57         else
 58             maxpt=(p<<1);
 59         swap(too[hashed[p]],too[hashed[maxpt]]);
 60         swap(heap[p],heap[maxpt]);
 61         swap(hashed[p],hashed[maxpt]);
 62         p=maxpt;
 63     }
 64     return ;
 65 }
 66 void change(int p,LL now)
 67 {
 68     heap[p]=now;
 69     while(p>1 && heap[p]<heap[p>>1])
 70     {
 71         swap(too[hashed[p]],too[hashed[p>>1]]);
 72         swap(heap[p],heap[p>>1]);
 73         swap(hashed[p],hashed[p>>1]);
 74         p>>=1;
 75     }
 76     return ;
 77 }
 78 int main()
 79 {
 80     scanf("%d",&T);
 81     while(T--)
 82     {
 83         scanf("%d%d",&n,&m);
 84         init();
 85         for(int i=1;i<=m;i++)
 86         {
 87             scanf("%d%d%d",&u,&v,&ve);
 88             addedge(u,v,ve);
 89             addedge(v,u,ve);
 90             val[u]+=ve;
 91             val[v]+=ve;
 92         }
 93         for(int i=1;i<=n;i++)
 94             add(val[i],i);
 95         ans=heap[1];
 96         for(int i=1;i<=n;i++)
 97         {
 98             u=hashed[1];
 99             len=heap[1];
100             ans=max(ans,len);
101             pop();
102             for(int j=head[u];j!=-1;j=edge[j].next)
103             {
104                 v=edge[j].to;
105                 if(too[v]<=htot)
106                 {
107                     val[v]-=edge[j].val;
108                     change(too[v],val[v]);
109                 }
110             }
111         }
112         printf("%lld\n",ans);
113     }
114     return 0;
115 }
View Code

 

G 命名规范问题

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld

题目描述

驼峰命名法是起变量名的一种规范,大致来说是用混合的大小写字母来构成变量名,在这个问题里你可以假设具体规则如下:

1.每个变量名由至少2个单词拼接构成,且每个单词长度至少为2;

2.每个单词的首字母必须大写,其他位置必须小写(除了变量名的第一个单词允许全部小写外)。

 

但是SK同学的英语很差,看到长长的变量名就很难脑补出是由哪些单词组成的,因此看驼峰命名法的代码十分头疼。

还有一种下划线命名法,规则比较简单,即各个单词之间用下划线'_'连接,且字母全部小写。

现在给你一些变量名,你能将其中符合驼峰命名法规范的变量转换成下划线命名法吗?

 

输入描述:

第一行是一个正整数T(≤ 20000),表示测试数据的组数,
每组测试数据只有一行,包含一个仅包含大小写英文字母且长度不超过20的变量名,
保证所有测试数据变量名长度总和不超过200000。

输出描述:

对于每组测试数据,输出一行,包含一个字符串,如果变量名符合驼峰命名法规范则将其改为下划线命名法,否则不变。
示例1

输入

10
mystring
myString
String
SS
my
mySString
mString
STRING
StrinG
IndexOfString

输出

mystring
my_string
String
SS
my
mySString
mString
STRING
StrinG
index_of_string



简单码农题,你自己看着办。orz

标程正则20行。我代码怎么那么挫~

 1 #include<bits/stdc++.h>
 2 #define clr(x) memset(x,0,sizeof(x))
 3 #define clr_1(x) memset(x,-1,sizeof(x))
 4 #define mod 1000000007
 5 #define LL long long
 6 #define INF 0x3f3f3f3f
 7 #define mp(x,y) make_pair(x,y)
 8 using namespace std;
 9 const int N=1e6+10;
10 int T;
11 char s1[N],s2[N];
12 int tot,num,n;
13 bool flag;
14 int main()
15 {
16     scanf("%d",&T);
17     while(T--)
18     {
19         scanf("%s",s1);
20         tot=0;
21         flag=0;
22         num=0;
23         n=strlen(s1);
24         for(int i=0;s1[i];i++)
25         {
26             if(i>0 && (s1[i]>='A' && s1[i]<='Z') && (s1[i-1]>='A' && s1[i-1]<='Z'))
27                 flag=1;
28             if(s1[i]>='A' && s1[i]<='Z')
29             {
30                 s2[tot++]='_';
31                 s2[tot++]=s1[i]-'A'+'a';
32                 num++;
33             }
34             else
35                 s2[tot++]=s1[i];
36         }
37         s2[tot]='\0';
38         if(s1[0]>='a' && s1[0]<='z')
39             num++;
40         if(num<2 || (n>=2 &&(s1[0]>='a' && s1[0]<='z') && (s1[1]>='A' && s1[1]<='Z')) || (s1[n-1]>='A' && s1[n-1]<='Z') )
41             flag=1;
42         if(flag)
43             printf("%s\n",s1);
44         else
45             printf("%s\n",(s1[0]>='a' && s1[0]<='z')?(s2):(s2+1));
46     }
47     return 0;
48 }
View Code

 

H 吾好梦中做题

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld

题目描述

SK同学最喜欢做梦了,因为梦里什么都有,甚至会有题目!

有一天,SK还真梦到了一个棘手的问题。

问题是这样的,在梦里出现了一个很长很长的只包含‘(’和‘)’的括号序列。按照梦里的指引,SK需要完成一些任务。任务分为两种:一是将某个给定位置的括号方向翻转一下,即原本是左括号则变为右括号,原本是右括号则变为左括号;二是询问以某个给定的位置为左端点的区间中最长的合法括号序列的长度。

合法括号序列是这样递归定义的:

1.()是合法括号序列;

2.如果A是合法的,那么(A)也是合法的;

3.如果A和B都合法,那么AB合法。

 

机智的SK在梦里瞬间解决了这些任务,但是他醒后却想不起来自己是如何做到的,于是请你来帮他回忆做法。

输入描述:

第一行是一个正整数T(≤ 10),表示测试数据的组数,
对于每组测试数据,
第一行是两个正整数n(≤ 500000)和m(≤ 500000),分别表示括号序列的长度以及任务个数,
第二行,一个只包含左右括号的字符串,表示初始的括号序列,
接下来m行,每行包含两个正整数x,y(1 ≤ x ≤ 2,1 ≤ y ≤ n),分别表示任务种类以及给定的位置,
保证所有测试数据的括号序列长度之和与任务数之和均不超过500000。

输出描述:

对于每个任务二,输出一行,包含一个整数,表示以给定的位置为左端点的区间中最长的合法括号序列的长度,如果找不到合法括号序列则输出0。
示例1

输入

1
7 5
()()())
2 2
2 1
1 2
2 3
2 1

输出

0
6
4
0

说明

对于第一个任务,以第二个括号为左端点的区间构成的序列有)、)(、)()、)()(、)()()和)()()),其中没有合法的括号序列,
对于第二个任务,以第一个括号为左端点的区间构成的序列有(、()、()(、()()、()()(、()()()和()()()),其中合法的括号序列为()、()()和()()(),长度最大值是6,
对于第三个任务,序列变为((()()),
对于第三个任务,以第三个括号为左端点的区间构成的序列有(、()、()(、()()和()()),其中合法的括号序列为()和()(),长度最大值是4,
对于第四个任务,以第一个括号为左端点的区间构成的序列有(、((、(((、((()、((()(、((()()和((()()),其中没有合法的括号序列。

我的写法差不多。

  1 #include<bits/stdc++.h>
  2 #define clr(x) memset(x,0,sizeof(x))
  3 #define mod 1000000007
  4 #define clr_1(x) memset(x,-1,sizeof(x))
  5 #define INF 0x3f3f3f3f
  6 #define LL long long
  7 #define pb push_back
  8 #define pbk pop_back
  9 #define ls(i) (i<<1)
 10 #define rs(i) (i<<1|1)
 11 #define mp make_pair
 12 using namespace std;
 13 const int N=5e5+10;
 14 int a[N],pre[N];
 15 char s[N];
 16 int T,n,m,q,op,x,t;
 17 void init()
 18 {
 19     pre[0]=0;
 20     return ;
 21 }
 22 struct node
 23 {
 24     int l,r,minx,tag;
 25 }tree[N<<2];
 26 inline void add(int i,int y)
 27 {
 28     tree[i].tag+=y,tree[i].minx+=y;
 29     return ;
 30 }
 31 inline void pushup(int i)
 32 {
 33     tree[i].minx=min(tree[ls(i)].minx,tree[rs(i)].minx);
 34     return ;
 35 }
 36 inline void pushdown(int i)
 37 {
 38     if(tree[i].tag!=0)
 39     {
 40         if(tree[i].l!=tree[i].r) add(ls(i),tree[i].tag),add(rs(i),tree[i].tag);
 41         tree[i].tag=0;
 42     }
 43     return ;
 44 }
 45 void init(int i,int l,int r)
 46 {
 47     tree[i]=(node){l,r};
 48     if(l==r)
 49     {
 50         tree[i].minx=pre[l];
 51         return;
 52     }
 53     int mid=(l+r)>>1;
 54     init(ls(i),l,mid);
 55     init(rs(i),mid+1,r);
 56     pushup(i);
 57     return ;
 58 }
 59 void update(int i,int l,int r,int x)
 60 {
 61     if(tree[i].l>=l && tree[i].r<=r)
 62     {
 63         add(i,x);
 64         return ;
 65     }
 66     pushdown(i);
 67     int mid=(tree[i].l+tree[i].r)>>1;
 68     if(l<=mid) update(ls(i),l,r,x);
 69     if(r>mid) update(rs(i),l,r,x);
 70     pushup(i);
 71     return ;
 72 }
 73 int query(int i,int x)
 74 {
 75     if(tree[i].l==tree[i].r) return tree[i].minx;
 76     pushdown(i);
 77     int mid=(tree[i].l+tree[i].r)>>1;
 78     if(mid>=x) return query(ls(i),x);
 79     else return query(rs(i),x);
 80 }
 81 int asklow(int i,int l,int r,int val)
 82 {
 83     if(tree[i].l>=l &&tree[i].r<=r)
 84     {
 85         if(tree[i].minx>=val) return n+1;
 86         if(tree[i].l==tree[i].r) return tree[i].l;
 87         pushdown(i);
 88         if(tree[ls(i)].minx<val) return asklow(ls(i),l,r,val);
 89         else return asklow(rs(i),l,r,val);
 90     }
 91     pushdown(i);
 92     int mid=(tree[i].l+tree[i].r)>>1;
 93     int ans=n+1;
 94     if(l<=mid) ans=min(asklow(ls(i),l,r,val),ans);
 95     if(r>mid && ans==n+1) ans=min(asklow(rs(i),l,r,val),ans);
 96     return ans;
 97 }
 98 int askequ(int i,int l,int r,int val)
 99 {
100     if(tree[i].l>=l &&tree[i].r<=r)
101     {
102         if(tree[i].minx>val) return -1;
103         if(tree[i].l==tree[i].r) return tree[i].l;
104         pushdown(i);
105         if(tree[rs(i)].minx==val) return askequ(rs(i),l,r,val);
106         else return askequ(ls(i),l,r,val);
107     }
108     pushdown(i);
109     int mid=(tree[i].l+tree[i].r)>>1;
110     int ans=-1;
111     if(r>mid) ans=max(askequ(rs(i),l,r,val),ans);
112     if(l<=mid && ans==-1) ans=max(askequ(ls(i),l,r,val),ans);
113     return ans;
114 }
115 int main()
116 {
117     scanf("%d",&T);
118     while(T--)
119     {
120         scanf("%d%d",&n,&q);
121         scanf("%s",s);
122         init();
123         for(int i=0;s[i];i++)
124         {
125             if(s[i]=='(')
126             {
127                 a[i+1]=1;
128                 pre[i+1]=pre[i]+a[i+1];
129             }
130             else
131             {
132                 a[i+1]=-1;
133                 pre[i+1]=pre[i]+a[i+1];
134             }
135         }
136         init(1,1,n);
137         for(int i=1;i<=q;i++)
138         {
139             scanf("%d%d",&op,&x);
140             if(op==1)
141             {
142                 a[x]=-a[x];
143                 update(1,x,n,a[x]*2);
144             }
145             else
146             {
147                 t=x-1>0?query(1,x-1):0;
148                 m=asklow(1,x,n,t);
149                 if(m!=n+1)
150                     printf("%d\n",m-x);
151                 else
152                 {
153                     m=askequ(1,x,n,t);
154                     if(m!=-1)
155                         printf("%d\n",m-x+1);
156                     else
157                         printf("0\n");
158                 }
159             }
160         }
161     }
162     return 0;
163 }
View Code

 

I 如何办好比赛

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld

题目描述

又到了一年一度的程序设计大赛了~
 
现在参赛选手在机房前排起了一列长队,这里面有萌新也有大佬,萌新都很仰慕大佬,由于大佬们的参赛,萌新们对这次比赛的精彩程度格外期待。对于每个萌新来说,他/她/它对本次的比赛的期待度为排在他/她/它前面的大佬的数量,而这次比赛的总期待度等于每个萌新的期待度之和。
 
SK同学作为本次比赛的组织者,希望比赛的期待度能够刚刚好,太低的话会让大家兴致不高,太高的话会被喷不满足预期。
 
现在SK同学可以交换任意相邻的两名参赛选手,但是比赛马上就要开始了,SK同学想知道最少要进行多少次交换才能使得这次比赛的总期待度刚好为k,你能帮帮他吗?

输入描述:

第一行是一个正整数T(≤ 10),表示测试数据的组数,
对于每组测试数据,
第一行是两个正整数n(≤ 1000000)和k(≤ 1000000000),分别表示队列长度和最终的比赛总期待度,
接下来一行包含n个字符,表示这个队列,第i个字符表示队列里的第i个人,'D'表示大佬,'M'表示萌新,保证不会出现其它字符。

输出描述:

对于每组测试数据,输出一行,包含一个整数,表示最少的交换次数,无解输出-1。
示例1

输入

2
3 1
DMM
3 3
DMM

输出

1
-1

你把大佬当做区间端点,你会发觉每个区间内萌新的期待度是相同的,就是前面的大佬的数量。然后一个交换操作就相当于把一个区间的萌新转移到相邻区间,对应的期待度也就是+1或-1。因此我们统计下当前期待度和要求期待度,他们的差就是要操作的最少次数。

如果要求期待度大于萌新数量*大佬数量,也就是萌新全部换到最右区间的情况,说明是无解的,输出-1。

 1 #include<bits/stdc++.h>
 2 #define clr(x) memset(x,0,sizeof(x))
 3 #define clr_1(x) memset(x,-1,sizeof(x))
 4 #define mod 1000000007
 5 #define LL long long
 6 #define INF 0x3f3f3f3f
 7 #define mp(x,y) make_pair(x,y)
 8 using namespace std;
 9 const int N=3e6+10;
10 int T,n,m,all;
11 LL ans,qdd;
12 char s[N];
13 int main()
14 {
15     scanf("%d",&T);
16     while(T--)
17     {
18         scanf("%d%lld",&n,&qdd);
19         scanf("%s",s);
20         m=0;
21         ans=0;
22         all=0;
23         for(int i=0;i<n;i++)
24         {
25             if(s[i]=='D')
26                 ++m;
27             else
28                 ans+=1LL*m,all++;
29         }
30         if(qdd>1LL*all*m)
31         {
32             printf("-1\n");
33             continue;
34         }
35         if(qdd<ans) swap(qdd,ans);
36         printf("%lld\n",qdd-ans);
37     }
38     return 0;
39 }
View Code

 

J 小白兔小灰兔

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
Special Judge, 64bit IO Format: %lld

题目描述

老山羊伯伯在地里收白菜,小白兔和小灰兔看见了就一起来帮忙。

他们干了半天,终于干完了。

羊伯伯:小灰兔,这车白菜送给你!

小灰兔:谢谢羊伯伯!

羊伯伯:小白兔,我也送你一车白菜!

小白兔:我不要白菜!给我一包白菜种子吧!

羊伯伯:好!给你~

小白兔:谢谢羊伯伯~

小灰兔把白菜拉到家里之后,就跟大家梦想中的生活一样,躺着啥都不干,吃吃吃,吃了玩~(好想一辈子都这样啊~小灰兔心想。)

小白兔把种子拿回去,打算开始勤劳地种白菜。然而他发现不是所有土地都能用来种白菜,只有被阳光照到的地方可以种白菜。

小白兔生活的星球可以看作二维平面中的一个简单多边形,太阳可以看作一个点。小白兔想知道,这个星球上一共有长度多少的土地可以用来种白菜。

输入描述:

第一行是一个正整数T(≤ 20),表示测试数据组数,

对于每组测试数据,

第一行是一个整数n(3≤ n≤ 10),表示简单多边形的顶点数,

接下来n行,每行是两个整数xi,yi(-10≤ xi,yi≤10),按照逆时针绕向给出简单多边形的n个顶点的坐标,

最后一行是两个整数x,y(-10≤ x,y≤10),表示太阳的坐标,保证太阳在多边形外且不在多边形任意一条边所在直线上。

输出描述:

对于每组测试数据,输出一行,包含一个实数,表示可以用来种白菜的土地的总长度,要求相对误差不超过

也就是说,令输出结果为a,标准答案为b,若满足,则输出结果会被认为是正确答案。

示例1

输入

2
4
0 0
2 0
2 2
0 2
4 1
4
0 0
2 0
2 2
0 2
4 4

输出

2.000000000000
4.000000000000


嗯多边形是简单多边形的简称,也就是他可以是凹的,但他的边不能相交。了解这点就基本上知道做法了。如果是凸的就直接取中点和视点连线看有没有线段单点相交。有的话就是看不到的,没有就是看得到的。对于凹多边形则需要把每条边按照视点和各端点连线和他的交点对这条边进行切割,然后这些切割的小线段再去看中点与视点连线有没有和其他线段规范相交。有则小线段会被挡住。

 

  1 #include<bits/stdc++.h>
  2 #define clr(x) memset(x,0,sizeof(x))
  3 #define clr_1(x) memset(x,-1,sizeof(x))
  4 #define mod 1000000007
  5 #define INF 0x3f3f3f3f
  6 #define LL long long
  7 #define pb push_back
  8 #define pbk pop_back
  9 #define ls(i) (i<<1)
 10 #define rs(i) (i<<1|1)
 11 #define mp make_pair
 12 using namespace std;
 13 typedef double db;
 14 const int N=5e5+10;
 15 const db eps=1e-9;
 16 int equzero(db t)//带精度大小判断
 17 {
 18     if(t>eps) return 1;
 19     if(t<-eps) return -1;
 20     return 0;
 21 }
 22 struct Point
 23 {
 24     db x,y;
 25     Point(){}
 26     Point(db _x,db _y):x(_x),y(_y) {}
 27     Point operator +(const Point &b) const //+
 28     {
 29         return Point(x+b.x,y+b.y);
 30     }
 31     Point operator -(const Point &b) const//-
 32     {
 33         return Point(x-b.x,y-b.y);
 34     }
 35     Point operator *(const db &b) const// 放大
 36     {
 37         return Point(x*b,y*b);
 38     }
 39     Point operator /(const db &b) const//缩小
 40     {
 41         return Point (x/b,y/b);
 42     }
 43     db dot(const Point &b) const//点积
 44     {
 45         return x*b.x+y*b.y;
 46     }
 47     db det(const Point &b) const//叉积
 48     {
 49         return x*b.y-b.x*y;
 50     }
 51     bool operator ==(const Point &b) const
 52     {
 53         return  equzero(x-b.x)==0 && equzero(y-b.y)==0;
 54     }
 55     bool operator !=(const Point &b) const
 56     {
 57         return !(Point(x,y)==b);
 58     }
 59     db mo() //
 60     {
 61         return sqrt(x*x+y*y);
 62     }
 63 }pt[N],u,v,mid;
 64 struct Line
 65 {
 66     Point a,b;
 67     Line (){}
 68     Line (Point _a,Point _b):a(_a),b(_b) {};
 69     bool quickrej(const Line &t) const//快速排斥判断
 70     {
 71         return equzero(min(a.x,b.x)-max(t.a.x,t.b.x))<=0 && equzero(min(t.a.x,t.b.x)-max(a.x,b.x))<=0 && equzero(min(a.y,b.y)-max(t.a.y,t.b.y))<=0 && equzero(min(t.a.y,t.b.y)-max(a.y,b.y))<=0;
 72     }
 73     db len() const
 74     {
 75         return (b-a).mo();
 76     }
 77     bool stra(const Line &t) const //跨立判断
 78     {
 79         return equzero((a-t.a).det(t.b-t.a)*(b-t.a).det(t.b-t.a))<0 && equzero((t.a-a).det(b-a)*(t.b-a).det(b-a))<0 ;
 80     }
 81     bool gfxj(const Line &t) const //规范相交
 82     {
 83         return quickrej(t) && stra(t);
 84     }
 85     bool on(const Point &t) const //点在线段上
 86     {
 87         Line p=Line(a,b);
 88         if(p.a.x>p.b.x)
 89             swap(p.a,p.b);
 90         if(equzero(t.x-p.a.x)<0 || equzero(t.x-p.b.x)>0)
 91             return false;
 92         if(equzero((p.a-t).det(p.b-t))==0)
 93             return true;
 94         else
 95             return false;
 96     }
 97     bool kddxj(const Line &t) const //可多点相交
 98     {
 99         return quickrej(t) && (stra(t) || on(t.a) || on(t.b) || t.on(a) || t.on(b));
100     }
101     bool para(const Line &t) const // 平行或在一条直线上
102     {
103         return equzero((a.y-b.y)*(t.a.x-t.b.x)-(t.a.y-t.b.y)*(a.x-b.x))==0 ;
104     }
105     db operator & (const Line &t) const //返回切点占直线比例,距a比例
106     {
107         if(equzero((a-b).det(t.a-t.b))==0)return -INF;
108         db tk=((a-t.a).det(t.a-t.b))/((a-b).det(t.a-t.b));
109         return equzero(tk)>=0 && equzero(tk-1)<=0 ? tk : -INF;
110     }
111 }le[N],lu,lv;
112 int n,m,T;
113 vector<db> cp;
114 db ans,ins,rate;
115 bool flag;
116 int main()
117 {
118     scanf("%d",&T);
119     while(T--)
120     {
121         scanf("%d",&n);
122         for(int i=0;i<=n;i++)
123             scanf("%lf%lf",&pt[i].x,&pt[i].y);
124         for(int i=0;i<n;i++)
125             le[i]=Line(pt[i],pt[(i+1)%n]);
126         ans=0;
127         for(int i=0;i<n;i++)
128         {
129             cp.clear();
130             for(int j=0;j<n;j++)
131             {
132                 ins=le[i]&Line(pt[n],pt[j]);
133                 if(ins>=-1) cp.pb(ins);
134             }
135             sort(cp.begin(),cp.end());
136             rate=0;
137             for(int j=0;j<cp.size()-1;j++)
138             {
139                 lu=Line(pt[n],le[i].a+(le[i].b-le[i].a)*((cp[j]+cp[j+1])/2));
140                 flag=0;
141                 for(int k=0;k<n;k++)
142                 {
143                     if(lu.gfxj(le[k]))
144                     {
145                         flag=1;
146                         break;
147                     }
148                 }
149                 if(!flag)
150                 {
151                     rate+=cp[j+1]-cp[j];
152                 }
153             }
154             ans+=rate*le[i].len();
155         }
156         printf("%.12f\n",ans);
157     }
158     return 0;
159 }
View Code

 

K 好学期来临吧

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld

题目描述

“只有投入才能获得真正的快乐” —— 鲁迅

SK同学这学期非常忙绿,他刚刚安排好n项工作的进行顺序,就发现BOSS又给了他m项工作,他只好想办法将这m项工作穿插到原来的n项工作之间进行(不改变原来n项工作的相对顺序)。

SK同学如果投入到某项工作中,就会收获一些快乐。之前有n项工作,现在又多了m项工作,本来,应该收获双倍的快乐,但是,SK同学发现自己不能连续投入到两个相邻的工作中。

SK同学想收获尽可能多的快乐,只好请熟练的你来帮助他了~

输入描述:

第一行是一个正整数T(≤ 10),表示测试数据的组数,
对于每组测试数据,
第一行是两个正整数n(≤ 1000)和m(≤ 100),分别表示原来安排好的n项工作和新增的m项工作,
接下来一行包含n个正整数,表示前n项工作投入时收获的快乐值,
接下来一行包含m个正整数,表示新增的m项工作投入时收获的快乐值,
所有快乐值都不超过100000。

输出描述:

对于每组测试数据,输出一行,包含一个整数,表示能收获的快乐值之和的最大值。
示例1

输入

2
2 2
2 2
1 1
3 2
8 2 7
1 5

输出

4
20

说明

对于第一组样例,可以将工作安排成[2,1,2,1],[1,2,1,2],[2,1,1,2]三种方案之一,然后选出2+2来投入。
对于第二组样例,可以将工作安排成[8,2,7,1,5],[8,1,5,2,7],[5,1,8,2,7],[8,2,5,1,7]五种方案之一,然后选出8+7+5来投入。


 

对应四种状态:0:选择前n个工作,最后一个(第i个)不投入 ;1:选择前n个工作,最后一个(第i个)不投入 ;2:选择后m个工作,不投入,也就是选择j;选择后m个工作,投入,也就是选择k。
 1 #include<bits/stdc++.h>
 2 #define clr(x) memset(x,0,sizeof(x))
 3 #define clr_1(x) memset(x,-1,sizeof(x))
 4 #define mod 1000000007
 5 #define INF 0x3f3f3f3f
 6 #define LL long long
 7 #define pb push_back
 8 #define pbk pop_back
 9 #define ls(i) (i<<1)
10 #define rs(i) (i<<1|1)
11 #define mp make_pair
12 using namespace std;
13 typedef double db;
14 const int N=1e3+10;
15 const int M=1e2+10;
16 int a[N],b[M];
17 int dp[2][M][M][4];
18 int n,m,T,ans;
19 int main()
20 {
21     scanf("%d",&T);
22     while(T--)
23     {
24       clr(dp);
25       scanf("%d",&n);
26       scanf("%d",&m);
27       for(int i=1;i<=n;i++)
28         scanf("%d",a+i);
29       for(int i=1;i<=m;i++)
30         scanf("%d",b+i);
31       sort(b+1,b+m+1);
32       ans=0;
33       for(int i=0;i<=n;i++)
34           for(int j=1;j<=m;j++)
35             for(int k=m;k>=j-1;k--)
36             {
37                 if(i>0)
38                 {
39                     dp[i&1][j][k][0]=max(max(dp[i&1^1][j][k][0],dp[i&1^1][j][k][1]),max(dp[i&1^1][j][k][2],dp[i&1^1][j][k][3]));
40                     dp[i&1][j][k][1]=max(dp[i&1^1][j][k][0],dp[i&1^1][j][k][2])+a[i];
41                 }
42                 if(j>1) dp[i&1][j][k][2]=max(max(dp[i&1][j-1][k][0],dp[i&1][j-1][k][1]),max(dp[i&1][j-1][k][2],dp[i&1][j-1][k][3]));
43                 if(k<m) dp[i&1][j][k][3]=max(dp[i&1][j][k+1][0],dp[i&1][j][k+1][2])+b[k+1];
44             }
45         for(int i=1;i<=m;i++)
46             ans=max(max(max(dp[n&1][i][i-1][0],dp[n&1][i][i-1][1]),max(dp[n&1][i][i-1][2],dp[n&1][i][i-1][3])),ans);
47         printf("%d\n",ans);
48     }
49     return 0;
50 }
View Code

 

K 好学期来临吧
posted @ 2018-05-07 19:25  hk_lin  阅读(572)  评论(0编辑  收藏  举报