【长沙集训】2017.10.28
1 抄代码
1.1 问题描述
J 君是机房的红太阳,每次模拟她总是 AK 虐场。然而在 NOIP2117 中,居然出现了另一位 AK 的选手 C 君!
这引起了组委会的怀疑,组委会认为 C 君有抄袭 J 君代码的嫌疑,原因是考试时 C 君正好 坐在 J 君旁边。于是组委会需要你帮她们鉴定一下 C 君是否抄了 J 君的代码。
NOIP2117 一共有 T 道题,每道题需要提交一份阿语言代码 (阿语言是 NOIP2117 的唯一可 用编程语言)。
一份阿语言代码只有一行,仅由小写字母,数字,空格和分号组成。
组委会认为,如果 C 君的代码可以由 J 君的代码经过若干次修改变量名操作得到,C 君就 抄了 J 君的代码。
一次修改变量名操作被定义为将代码中的所有小写字母 x 替换为小写字母 y(此处 x, y 代指 任意小写字母)。
请你告诉组委会,对于每道题,C 君是否抄了 J 君的代码。
1.2 输入格式
第一行一个正整数 T。
接下来 2T 行,第 2i 行代表 J 君对于第 i 道题的提交代码,第 2i + 1 行代表 C 君对于第 i 道题的提交代码。
1.3 输出格式
输出 T 行,如果对于第 i 道题,C 君抄了 J 君的代码,请在第 i 行输出1,否则请在第 i 行 输出0。
1.4 样例输入
5
int x;
int y;
double a;
double aa;
float 1
float 2
string s;
double d;
print thisismycode;
float tooooooooooo;
1.5 样例输出
1
0
0
1
1
1.6 数据规模与约定
10% 的数据满足代码中不包含字母。
另外 30% 的数据满足代码中只包含字母。
100% 的数据满足 T ≤ 1000,每行代码中不会包含超过 1000 个字符。
签到水题
注意linux下\n好像不对,就判\n||\r也ok了。
//Twenty
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<vector>
#include<cmath>
#include<queue>
#include<ctime>
const int maxn=100005;
typedef long long LL;
using namespace std;
int T,db[27],sza,szb;
char a[maxn],b[maxn];
void read(char c[],int &sz) {
char ch=getchar(); sz=0;
while(ch=='\n'||ch=='\r') ch=getchar();
while(ch!='\n'&&ch!='\r') {
c[++sz]=ch;
ch=getchar();
}
}
int check() {
read(a,sza);
read(b,szb);
memset(db,-1,sizeof(db));
if(sza!=szb) return 0;
for(int i=1;i<=sza;i++) {
if(a[i]>='a'&&a[i]<='z'&&b[i]>='a'&&b[i]<='z') {
if(db[a[i]-'a']==-1) db[a[i]-'a']=b[i]-'a';
else if(db[a[i]-'a']!=b[i]-'a') return 0;
}
else if(a[i]!=b[i]) return 0;
}
return 1;
}
void init() {
scanf("%d",&T);
for(int i=1;i<=T;i++)
printf("%d\n",check());
}
#define DEBUG
int main() {
#ifdef DEBUG
freopen("copycat.in","r",stdin);
freopen("copycat.out","w",stdout);
#endif
init();
return 0;
}
2 做运动
2.1 问题描述
一天,Y 君在测量体重的时候惊讶的发现,由于常年坐在电脑前认真学习,她的体重有了突 飞猛进的增长。
幸好 Y 君现在退役了,她有大量的时间来做运动,她决定每天从教学楼跑到食堂来减肥。
Y 君将学校中的所有地点编号为 1 到 n,其中她的教学楼被编号为 S,她的食堂被编号为 T, 学校中有 m 条连接两个点的双向道路,保证从任意一个点可以通过道路到达学校中的所有点。
然而 Y 君不得不面临一个严峻的问题,就是天气十分炎热,如果 Y 君太热了,她就会中暑。
于是 Y 君调查了学校中每条路的温度 t,及通过一条路所需的时间 c。
Y 君在温度为 t 的地 方跑单位时间,就会使她的热量增加 t。
由于热量过高 Y 君就会中暑,而且 Y 君也希望在温度较低的路上跑,她希望在经过的所有 道路中最高温度最低的前提下,使她到达食堂时的热量最低 (从教学楼出发时,Y 君的热量为 0)。
请你帮助 Y 君设计从教学楼到食堂的路线,以满足她的要求。你只需输出你设计的路线中所 有道路的最高温度和 Y 君到达食堂时的热量。
2.2 输入格式
第一行由一个空格隔开的两个正整数 n, m,代表学校中的地点数和道路数。
接下来 m 行,每行由一个空格隔开的四个整数 a, b, t, c 分别代表双向道路的两个端点,温度 和通过所需时间。
最后一行由一个空格隔开的两个正整数 S, T,代表教学楼和食堂的编号。
注意:输入数据量巨大,请使用快速的读入方式。
2.3 输出格式
一行由一个空格隔开的两个整数,分别代表最高温度和热量。
2.4 样例输入
5 6
1 2 1 2
2 3 2 2
3 4 3 4
4 5 3 5
1 3 4 1
3 5 3 6
1 5
2.5 样例输出
3 24
2.6 数据规模与约定
10% 的数据满足 t = 0
另外 10% 的数据满足 c = 0
另外 30% 的数据满足 n ≤ 2000
100% 的数据满足 n ≤ 5 × 105 , m ≤ 106 , 0 ≤ t ≤ 10000, 0 ≤ c ≤ 108 , 1 ≤ a, b, S, T ≤ n, S ̸= T
九点左右就打完了前两题,觉得贼简单,然后就在同一个坑又栽了一次。
二分+最短路,T得你妈都不认识。
正解边排序,并查集维护。
怎么还没记住这套路,怎么就不带点脑子。
//Twenty
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<vector>
#include<cmath>
#include<queue>
#include<ctime>
#define INF 1e18
const int maxn=5e5+5;
const int maxm=1e6+5;
typedef long long LL;
using namespace std;
int n,m,l=0,r=10000,s,t,sz,fa[maxn];
LL ans1,ans2;
namespace fastIO {
const int sz=1<<15|1;
char ch,buf[sz],*l,*r;
void gechar(char &c) {
if(l==r) r=(l=buf)+fread(buf,1,sz,stdin);
c = l==r?(char)EOF:*l++;
}
template<typename T> void read(T &x) {
int f=1; x=0; gechar(ch);
while(ch!='-'&&(ch<'0'||ch>'9')) gechar(ch);
if(ch=='-') f=-1,gechar(ch);
for(;ch>='0'&&ch<='9';gechar(ch)) x=x*10+ch-'0'; x*=f;
}
}
struct edge {
int u,v,t;
LL val;
edge(){}
edge(int u,int v,int t,LL val):u(u),v(v),t(t),val(val){}
friend bool operator <(const edge&A,const edge&B) {
return A.t<B.t||(A.t==B.t&&A.val<B.val);
}
}e[maxm];
int ecnt,fir[maxn],nxt[maxm<<1],to[maxm<<1];
LL val[maxm<<1],dis[maxn];
void add(int u,int v,LL vv) {
nxt[++ecnt]=fir[u]; fir[u]=ecnt; to[ecnt]=v; val[ecnt]=vv;
nxt[++ecnt]=fir[v]; fir[v]=ecnt; to[ecnt]=u; val[ecnt]=vv;
}
int que[maxn<<1],vis[maxn],ql,qr;
int spfa() {
ql=maxn+1; qr=maxn;
for(int i=1;i<=n;i++) dis[i]=INF,vis[i]=0;
dis[s]=0;
que[++qr]=s; vis[s]=1;
while(ql<=qr) {
int x=que[ql++];
vis[x]=0;
for(int i=fir[x];i;i=nxt[i]) {
if(dis[to[i]]>dis[x]+val[i]) {
dis[to[i]]=dis[x]+val[i];
if(!vis[to[i]]) {
vis[to[i]]=1;
if(ql<=qr&&dis[to[i]]<=dis[que[ql]]) que[--ql]=to[i];
else que[++qr]=to[i];
}
}
}
}
}
int find(int x) {
return x==fa[x]?x:fa[x]=find(fa[x]);
}
void work() {
for(int i=1;i<=n;i++) fa[i]=i;
sort(e+1,e+sz+1);
for(int i=1;i<=sz;i++) {
int u=e[i].u,v=e[i].v;
ans1=e[i].t;
int x=find(u),y=find(v);
add(u,v,e[i].val);
if(x!=y) {
fa[x]=y;
}
if(find(s)==find(t)) {
for(int k=i+1;e[k].t==ans1;k++)
add(e[k].u,e[k].v,e[k].val);
break;
}
}
spfa();
ans2=dis[t];
printf("%lld %lld\n",ans1,ans2);
}
void init() {
fastIO::read(n);
fastIO::read(m);
for(int i=1;i<=m;i++) {
int u,v,t,c;
fastIO::read(u);
fastIO::read(v);
fastIO::read(t);
fastIO::read(c);
e[++sz]=edge(u,v,t,(LL)t*c);
}
fastIO::read(s);
fastIO::read(t);
}
#define DEBUG
int main() {
#ifdef DEBUG
freopen("running.in","r",stdin);
freopen("running.out","w",stdout);
#endif
init();
work();
return 0;
}
3 大逃杀
3.1 问题描述
自从 Y 君退役之后,她就迷上了吃鸡,于是她决定出一道吃鸡的题。
Y 君将地图上的所有地点标号为 1 到 n,地图中有 n − 1 条双向道路连接这些点,通过一条 双向道路需要一定时间,保证从任意一个点可以通过道路到达地图上的所有点。
有些点上可能有资源,Y 君到达一个有资源的点后,可以选择获取资源来使自己的武力值增 加 wi,也可以选择不获取资源。
如果 Y 君获取了一个点上的资源,这个点上的资源就会消失,获 取资源不需要时间。 有些点上可能有敌人,Y 君到达一个有敌人的点后,必须花费 ti 秒伏地与敌人周旋,并最终 将敌人消灭。
如果 Y 君消灭了一个点上的敌人,这个点上的敌人就会消失。Y 君不能无视敌人继 续前进,因为这样会被敌人攻击。
如果一个点上既有资源又有敌人,Y 君必须先消灭敌人之后才能获取资源,否则就会被敌人 突袭。
游戏开始时,Y 君可以空降到任意一个点上,接下来,她有 T 秒进行行动,T 秒后她就必须 前往中心区域送快递。
Y 君希望她前往中心区域送快递时,武力值尽可能大,请你帮助 Y 君设计 路线,以满足她的要求。
你只需输出 T 秒后 Y 君的武力值。
3.2 输入格式
第一行由单个空格隔开的两个正整数 n, T,代表点数和时间。
第二行 n 个由单个空格隔开的非负整数代表 wi,如果 wi = 0 代表该点没有武器,第三行 n 个由单个空格隔开的非负整数代表 ti,如果 ti = 0 代表该点没有敌人。
接下来 n − 1 行每行由单个空格隔开的 3 个非负整数 a, b, c 代表连接 a 和 b 的双向道路,通 过这条道路需要 c 秒。
3.3 输出格式
输出一行一个整数代表 T 秒后 Y 君的武力值。
3.4 样例输入
17 54
5 5 1 1 1 25 1 10 15 3 6 6 66 4 4 4 4
0 1 3 0 0 0 1 3 2 0 6 7 54 0 0 0 0
1 8 3
2 8 3
8 7 7
7 13 0
7 14 0
15 14 2
16 14 3
17 14 5
7 9 4
9 10 25
10 11 0
10 12 0
7 6 20
3 6 3
3 4 3
3 5 3
3.5 样例输出
68
3.6 数据规模与约定
测试点 特殊性质
1 wi = 0
2 ti = 0
3 以 i 为端点的双向道路不会超过两条
4
5 2 到 n 号点均有双向道路与1 号点相连
6
7 保证数据随机生成
8
9 N/A
10
100% 的数据满足 n, T ≤ 300, 0 ≤ wi , ti , c ≤ 106 , 1 ≤ a, b ≤ n。
树dp。
一眼发现跟那个到树上一坨点最后一个不用回来求最短路径有异曲同工之妙。
那是个套路,所有边加起来乘2,减去最高深度。
然后发现起点不确定,就是减去直径咯。
当时那题也可以动规搞,去了回来或者去了不回来。
在这题上就考虑动规,也就是说最多有两次可以下去了不回来。
dp[i][j][k]代表i点和它的子树共分配j的时间,k次下去没有回来的最大得分。
注意的是,因为十分坑爹的这些路径有些不需要时间,更新就有一个先后,否则会发生不需要时间的点被反复计算的情况。
然后就会被卡成40。
于是按照拓扑序更新咯。
//Twenty
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<vector>
#include<cmath>
#include<queue>
#include<ctime>
#define INF 1e18;
const int maxn=305;
typedef long long LL;
using namespace std;
int n,ti,wl[maxn],sj[maxn],str;
LL g[maxn][maxn][3],ans;
namespace fastIO {
const int sz=1<<15|1;
char ch,buf[sz],*l,*r;
void gechar(char &c) {
if(l==r) r=(l=buf)+fread(buf,1,sz,stdin);
c = l==r?(char)EOF:*l++;
}
template<typename T> void read(T &x) {
int f=1; x=0; gechar(ch);
while(ch!='-'&&(ch<'0'||ch>'9')) gechar(ch);
if(ch=='-') f=-1,gechar(ch);
for(;ch>='0'&&ch<='9';gechar(ch)) x=x*10+ch-'0'; x*=f;
}
}
int ecnt,fir[maxn],nxt[maxn<<1],to[maxn<<1],val[maxn<<1];
void add(int u,int v,int w) {
nxt[++ecnt]=fir[u]; fir[u]=ecnt; to[ecnt]=v; val[ecnt]=w;
nxt[++ecnt]=fir[v]; fir[v]=ecnt; to[ecnt]=u; val[ecnt]=w;
}
void dfs(int x,int fa) {
sj[x]=min(sj[x],ti+1);
g[x][sj[x]][0]=g[x][sj[x]][1]=g[x][sj[x]][2]=wl[x];
for(int i=0;i<sj[x];i++)
g[x][i][0]=g[x][i][1]=g[x][i][2]=-INF;
for(int i=fir[x];i;i=nxt[i]) if(to[i]!=fa) {
int y=to[i];
dfs(y,x);
for(int j=ti;j>=val[i];j--) {
for(int k=0;k+val[i]<=j;k++) {
if(k+2*val[i]<=j) g[x][j][2]=max(g[x][j][2],g[x][j-(k+2*val[i])][2]+g[y][k][0]);
if(k+2*val[i]<=j) g[x][j][2]=max(g[x][j][2],g[x][j-(k+2*val[i])][0]+g[y][k][2]);
g[x][j][2]=max(g[x][j][2],g[x][j-(k+val[i])][1]+g[y][k][1]);
if(k+2*val[i]<=j) g[x][j][1]=max(g[x][j][1],g[x][j-(k+2*val[i])][1]+g[y][k][0]);
g[x][j][1]=max(g[x][j][1],g[x][j-(k+val[i])][0]+g[y][k][1]);
if(k+2*val[i]<=j) g[x][j][0]=max(g[x][j][0],g[x][j-(k+2*val[i])][0]+g[y][k][0]);
}
}
}
for(int i=0;i<=ti;i++) for(int j=0;j<=2;j++) ans=max(g[x][i][j],ans);
}
void work() {
if(!str) {
printf("0\n");
return;
}
dfs(str,0);
printf("%lld\n",ans);
}
void init() {
fastIO::read(n);
fastIO::read(ti);
for(int i=1;i<=n;i++) {
fastIO::read(wl[i]);
if(!str&&wl[i]) str=i;
}
for(int i=1;i<=n;i++)
fastIO::read(sj[i]);
for(int i=1;i<n;i++) {
int a,b,c;
fastIO::read(a);
fastIO::read(b);
fastIO::read(c);
add(a,b,c);
}
}
#define DEBUG
int main() {
#ifdef DEBUG
freopen("toyuq.in","r",stdin);
freopen("toyuq.out","w",stdout);
#endif
init();
work();
return 0;
}