2017 清北济南考前刷题Day 2 afternoon
期望得分:100+60+70=230
实际得分:0+60+0=60
T1
可以证明如果一对括号原本就匹配,那么这对括号在最优解中一定不会被分开
所以用栈记录下没有匹配的括号
最后栈中一定是 一堆右括号然后一堆左括号
ans=栈中右括号/2 上取整 + 栈中左括号 /2 上取整
#include<cstdio>
#include<cstring> using namespace std; #define N 100001 int top;
char st[N]; char s[N]; int main()
{
freopen("shower.in","r",stdin);
freopen("shower.out","w",stdout);
scanf("%s",s+);
int len=strlen(s+);
for(int i=;i<=len;i++)
if(s[i]=='(') st[++top]='(';
else if(top && st[top]=='(') top--;
else st[++top]=')';
int ans=;
int i;
for(i=;i<=top;i++)
if(st[i]!=')') break;
i--;
printf("%d",(i+)/+(top-i+)/);
}
考试的时候 碰到右括号,没有判断此时栈顶是否是左括号
括号匹配只需要判断 栈中是否有东西,因为一定是 左括号
这里因为有不合法的情况,所以需要判断
T2
前缀和二分
#include<cstdio>
#include<iostream> #define N 1000004 using namespace std; bool vis[N];
int p[N],cnt; long long sum[N]; void read(int &x)
{
x=; char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) { x=x*+c-''; c=getchar(); }
} void pre()
{
for(int i=;i<N;i++)
{
if(!vis[i])
{
p[++cnt]=i;
sum[cnt]=sum[cnt-]+p[cnt];
}
for(int j=;j<=cnt;j++)
{
if(i*p[j]>=N) break;
vis[i*p[j]]=true;
if(i%p[j]==) break;
}
}
} int main()
{
freopen("diary.in","r",stdin);
freopen("diary.out","w",stdout);
pre();
int T,n,k;
read(T);
int l,r,mid,tmp;
while(T--)
{
read(n); read(k);
l=k;r=lower_bound(p+,p+cnt+,n)-p;
tmp=-;
while(l<=r)
{
mid=l+r>>;
if(sum[mid]-sum[mid-k]<=n) tmp=mid,l=mid+;
else r=mid-;
}
printf("%d\n",tmp==- ? - : sum[tmp]-sum[tmp-k]);
}
}
60 暴力
#include<cstdio>
#include<iostream>
#include<algorithm> using namespace std; int T; #define N 1000004 typedef long long LL; int p[N],cnt;
bool vis[N]; LL sum[N]; struct node
{
int n,k,id;
}e[]; void read(int &x)
{
x=; char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) { x=x*+c-''; c=getchar(); }
} void pre()
{
for(int i=;i<N;i++)
{
if(!vis[i]) p[++cnt]=i;
for(int j=;j<=cnt;j++)
{
if(i*p[j]>=N) break;
vis[i*p[j]]=true;
if(i%p[j]==) break;
}
}
for(int i=;i<=cnt;i++) sum[i]=sum[i-]+p[i];
} namespace solve1
{
void work()
{
int n,k,m; bool ok;
for(int i=;i<=T;i++)
{
n=e[i].n; k=e[i].k;
m=lower_bound(p+,p+cnt,n)-p;
ok=false;
for(int i=m;i>=k && !ok ;i--)
if(sum[i]-sum[i-k]<=n) { printf("%d\n",sum[i]-sum[i-k]); ok=true; }
if(!ok) puts("-1");
}
}
} namespace solve2
{
int ans[]; bool cmp(node p,node q)
{
return p.k<q.k;
} void work()
{
sort(e+,e+T+,cmp);
int r=lower_bound(p+,p+cnt+,e[].n)-p;
int l=r;
int now=;
while(now<=T)
{
l=min(l,r-e[now].k+);
if(l<=) break;
while(l> && sum[r]-sum[l-]>e[now].n) r--,l--;
if(sum[r]-sum[l-]>e[now].n) break;
ans[e[now].id]=sum[r]-sum[l-];
now++;
}
for(;now<=T;now++) ans[e[now].id]=-;
for(int i=;i<=T;i++) printf("%d\n",ans[i]);
}
} void init()
{
read(T); bool flag1=true,flag2=true;
for(int i=;i<=T;i++)
{
read(e[i].n); read(e[i].k);
if(e[i].n>) flag1=false;
if(e[i].n!=e[].n) flag2=false;
e[i].id=i;
}
if(flag1 || T==) solve1::work();
else if(flag2) solve2::work();
} int main()
{
freopen("diary.in","r",stdin);
freopen("diary.out","w",stdout);
pre();
init();
}
T3
这算个DP套DP吗
设g[i][j] 表示 在第i棵树中,所有的点到j的权值和
F(t)=F(a)+F(b)+ size[a]*size[b]*l + g[a][c]*size[b] + g[b][d]*size[a]
size在合并的过程中 维护即可
求 g[i][j] :
设dis[i][j][k] 在第i棵树中,j到k的距离
设现在要求g[t][k],有一条长为L的边连接c和d
g[t][k]=g[A][k]+g[B][d]+(L+dis[A][k][c])*size[B]
求dis[i][j][k]:
如果本就是在一棵树里,直接= dis[A][j][k]
否则
假设有一条长为L的边连接了树A中第点c和树B中的点d,构成了第t棵树
现在要求dis[t][p1][p2]
=dis[A][c][p1]+dis[B][d][p2]+L
g数组和dis数组不可能都存下来,每一次合并只涉及两个点,记忆化搜索即可
注意:如果某点是在合并的第二棵树里,编号还要减去第一棵树的大小
#include<map>
#include<cstdio>
#include<iostream>
#include<algorithm> using namespace std; typedef long long LL; const int mod=1e9+; struct node
{
int p;
LL p1,p2;
node() {}
node(int i,LL j,LL k)
{
p=i;
p1=min(j,k);
p2=max(j,k);
}
bool operator < (node a) const
{
if(p!=a.p) return p<a.p;
if(p1!=a.p1) return p1<a.p1;
return p2<a.p2;
}
}; map<pair<int,LL>,int>g;
map<node,int>dis; int id1[],id2[],len[];
LL num1[],num2[]; LL siz[]; int f[]; void read(int &x)
{
x=; char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) { x=x*+c-''; c=getchar(); }
} void read(LL &x)
{
x=; char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) { x=x*+c-''; c=getchar(); }
} int getDIS(int i,LL j,LL k)
{
if(!i) return ;
if(j==k) return ;
node x=node(i,j,k);
if(dis.count(x)) return dis[x];
if(j<siz[id1[i]])
{
if(k<siz[id1[i]]) return dis[x]=getDIS(id1[i],j,k);
return dis[x]=(1LL*getDIS(id1[i],num1[i],j)+len[i]+getDIS(id2[i],num2[i],k-siz[id1[i]]))%mod;
}
else
{
if(k<siz[id1[i]]) return dis[x]=(1LL*getDIS(id1[i],num1[i],k)+len[i]+getDIS(id2[i],num2[i],j-siz[id1[i]]))%mod;
return dis[x]=getDIS(id2[i],j-siz[id1[i]],k-siz[id1[i]]);
}
} int getG(int i,LL j)
{
if(!i) return ;
pair<int,LL>pr = make_pair(i,j);
if(g.count(pr)) return g[pr];
if(j<siz[id1[i]]) return g[pr]=((1LL*getDIS(id1[i],num1[i],j)+len[i])*(siz[id2[i]]%mod)%mod+getG(id2[i],num2[i])+getG(id1[i],j))%mod;
return g[pr]=((1LL*getDIS(id2[i],num2[i],j-siz[id1[i]])+len[i])*(siz[id1[i]]%mod)%mod+getG(id1[i],num1[i])+getG(id2[i],j-siz[id1[i]]))%mod;
} int main()
{
freopen("cloth.in","r",stdin);
freopen("cloth.out","w",stdout);
int m;
read(m);
siz[]=;
for(int i=;i<=m;i++)
{
read(id1[i]); read(id2[i]); read(num1[i]); read(num2[i]); read(len[i]);
f[i]=(f[id1[i]]+f[id2[i]]+(siz[id1[i]]%mod)*(siz[id2[i]]%mod)%mod*len[i]%mod+getG(id1[i],num1[i])*(siz[id2[i]]%mod)%mod+getG(id2[i],num2[i])*(siz[id1[i]]%mod)%mod)%mod;
siz[i]=siz[id1[i]]+siz[id2[i]];
cout<<f[i]<<'\n';
}
}
2017 清北济南考前刷题Day 2 afternoon的更多相关文章
- 2017 清北济南考前刷题Day 7 afternoon
期望得分:100+100+30=230 实际得分:100+100+30=230 1. 三向城 题目描述 三向城是一个巨大的城市,之所以叫这个名字,是因为城市中遍布着数不尽的三岔路口.(来自取名力为0的 ...
- 2017 清北济南考前刷题Day 1 afternoon
期望得分:80+30+70=180 实际得分:10+30+70=110 T1 水题(water) Time Limit:1000ms Memory Limit:128MB 题目描述 LYK出了道水 ...
- 2017 清北济南考前刷题Day 3 afternoon
期望得分:100+40+100=240 实际得分:100+40+100=240 将每个联通块的贡献乘起来就是答案 如果一个联通块的边数>点数 ,那么无解 如果边数=点数,那么贡献是 2 如果边数 ...
- 2017 清北济南考前刷题Day 4 afternoon
期望得分:30+50+30=110 实际得分:40+0+0=40 并查集合并再次写炸... 模拟更相减损术的过程 更相减损术,差一定比被减数小,当被减数=减数时,停止 对于同一个减数来说,会被减 第1 ...
- 2017 清北济南考前刷题Day 6 afternoon
期望得分:100+100+30=230 实际得分: 正解: 枚举最高的位,这一位m是1但实际用了0 然后剩余的低位肯定是 正数就用1,负数用0 考场思路:数位DP #include<cstdio ...
- 2017 清北济南考前刷题Day 5 afternoon
期望得分:100+100+30=230 实际得分:0+0+0=30 T1 直接模拟 #include<cstdio> #include<iostream> using name ...
- 2017 清北济南考前刷题Day 3 morning
实际得分:100+0+0=100 T1 右上角是必败态,然后推下去 发现同行全是必胜态或全是必败态,不同行必胜必败交叉 列同行 所以n,m 只要有一个是偶数,先手必胜 #include<cstd ...
- 2017 清北济南考前刷题Day 7 morning
期望得分:100+50+20=170 实际得分:10+50+20=80 1. 纸牌 题目描述 在桌面上放着n张纸牌,每张纸牌有两面,每面都写着一个非负整数.你的邪王真眼可以看到所有牌朝上的一面和朝下的 ...
- 2017 清北济南考前刷题Day 6 morning
T1 贪心 10 元先找5元 20元 先找10+5,再找3张5 #include<cstdio> using namespace std; int m5,m10,m20; int main ...
随机推荐
- B3
吴晓晖(组长) 过去两天完成了哪些任务 一些细节的debug,部分优化,算法中有关记录的部分 展示GitHub当日代码/文档签入记录 接下来的计划 推荐算法 还剩下哪些任务 组员:刘帅珍 过去两天完成 ...
- 我的JAVA运算符理解
基本概念 原码,反码,补码 只需要记住这几句就够了 1.二进制的最高位是符号位:0表示正数,1表示负数 2.正数的原码,反码,补码都一样 3.负数的反码=它的原码符号位不变,其他位取反 4.负数的补 ...
- JS计算两个日期之间的天数,时间差计算
1.日期之间的天数计算 //计算天数差的函数,通用 function DateDiff(sDate1, sDate2) { //sDate1和sDate2是2017-9-25格式 var aDate, ...
- 优先队列的一种实现--堆ADT
二叉堆的两个重要性质: 1.结构性,为完全二叉树,可以用数组方便地表示.2.堆序性:树中每个节点的关键字值大于或等于其父节点的关键字值. 二叉堆的数据结构声明如下: struct HeapStruct ...
- beta阶段成果展示博客
跟着我们一一点一点揭开蒙娜丽莎的微笑 - 本次beta阶段之前,我们团队,对其他组在事后诸葛亮期间对我们的评价进行深刻的审视,特别是缺点方面,开了好几次的站立会议,专门讨论beta的主要方向和任务.最 ...
- 评论alpha发布以及PSP
讲解顺序: 1. 俄罗斯方块 武志远 俄罗斯方块有自己新颖的玩法加在里面 ,可以进行游戏,界面友好但不美观,与传统玩法相比增加了经验值,这是一个很好的创意,游戏运行也很流畅,并找到两名同学现场体 ...
- PAT 甲级 1146 Topological Order
https://pintia.cn/problem-sets/994805342720868352/problems/994805343043829760 This is a problem give ...
- PAT 1067 试密码
https://pintia.cn/problem-sets/994805260223102976/problems/994805266007048192 当你试图登录某个系统却忘了密码时,系统一般只 ...
- php SPL标准库iterator和ArrayAccess的学习
最近在补充学习php基础的时候看到了spl的介绍,学习了一下iterator和arrayAccess的使用,iterator主要是对象的迭代,一般可以用在容器里面,或者工厂模式里面,最常见的应用场景就 ...
- dividend = Integer.parseInt(args[0])参数问题
先来一段代码: package yichang; public class MyExceptionTest { public static void main(String[] args) { int ...