2015暑假训练(UVALive 5983 - 5992)线段树离线处理+dp
A: http://acm.hust.edu.cn/vjudge/contest/view.action?cid=83690#problem/A
题意:N*M的格子,从左上走到右下,要求在每个点的权值必须大于0,问起始的时候必须有多少能量
思路:二分答案
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
typedef long long LL;
const int maxn=510;
const int maxm=1010;
const int MOD=1e9+7;
const int INF=0x3f3f3f3f;
int N,M;
int a[maxn][maxn];
int dp[maxn][maxn];
bool can(int x){
for(int i=0;i<=N;i++){
for(int j=0;j<=M;j++){
dp[i][j]=-INF;
}
}
dp[1][1]=x;
if(dp[1][1]<=0)return false;
for(int i=1;i<=N;i++){
for(int j=1;j<=M;j++){
if(i==1&&j==1)continue;
dp[i][j]=max(dp[i-1][j],dp[i][j-1])+a[i][j];
if(dp[i][j]<=0)dp[i][j]=-INF;
}
}
return dp[N][M]>=0;
}
int main(){
int T;
scanf("%d",&T);
while(T--){
scanf("%d%d",&N,&M);
for(int i=1;i<=N;i++){
for(int j=1;j<=M;j++){
scanf("%d",&a[i][j]);
}
}
int l=0,r=INF;
while(l<r){
int mid=(l+r)>>1;
if(can(mid))r=mid;
else l=mid+1;
}
printf("%d\n",r);
}
return 0;
}
D: http://acm.hust.edu.cn/vjudge/contest/view.action?cid=83690#problem/D
题意:N个人,两两之间比赛,然后告诉你每个人赢了多少场,但里面存在错误,问最小修改多少分,能符合常理
思路:每次枚举分数最高的,然后把他输得分配下去,更新答案
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
typedef long long LL;
const int maxn=100010;
const int maxm=1010;
const int MOD=1e9+7;
const int INF=0x3f3f3f3f;
int N;
int a[maxn];
int main(){
int T;
scanf("%d",&T);
while(T--){
scanf("%d",&N);
int sum=0;
for(int i=1;i<=N;i++){
scanf("%d",&a[i]);
}
int ans=0;
for(int i=N;i>=1;i--){
sort(a+1,a+1+i);
if(a[i]>=i){
ans+=a[i]-i+1;
a[i]=i-1;
}
int cha=i-a[i]-1;
for(int j=i-1;j>=i-cha;j--){
a[j]--;
if(a[j]<0){
ans++;
a[j]=0;
}
}
}
printf("%d\n",ans);
}
return 0;
}
前1个人,至少0场胜利,他可能全部败给后面的人,也可能赢了后面某几个人。
前2个人,至少要有1场胜利,他们之间必须有一人获胜,如果不够,就需要补足。如果大于1,表示他们之中有人赢了后面某几人。
前3个人,至少要有3场胜利 ………………
前4个人,至少要有6场胜利 ………………
等等…………
前n个人(即所有的人)时,至少要有n(n-1)/2场胜利,不够则补足。但如果大于n(n-1)/2,就表示胜利场数超了,此时需要将胜利场数更改回n(n-1)/2 。
#include<cstdio>
#include<algorithm>
#include<iostream>
using namespace std;
int main(){
int s[51],p[51];
int t,i,n,res;
for(cin>>t;t--;){
cin>>n;
for(i=0,res=0;i<n;i++){
cin>>s[i];
p[i]=i?p[i-1]+i:0;
}
sort(s,s+n);
for(i=0;i<n;i++){
s[i]=i?s[i-1]+s[i]:s[i];
if(p[i]>=s[i])
res+=p[i]-s[i],s[i]=p[i];
}
cout<<res+s[n-1]-p[n-1]<<endl;
}
return 0;
}
H: http://acm.hust.edu.cn/vjudge/contest/view.action?cid=83690#problem/H
题意:找有多少个字串包含最大值和最小值,找有多少个子序列包含最大值最小值
思路:对于第一个,可以预处理出里每个位置最近的最大值和最小值,然后枚举开头。对于第二问设最大值的个数为cnt1,最小值的个数为cnt2,那么答案就是2N−2N−cnt1−2N−cnt2+2N−cnt1−cnt2
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
typedef long long LL;
const int maxn=100010;
const int maxm=1010;
const int MOD=1e9+7;
const int INF=0x3f3f3f3f;
int N;
int a[maxn];
LL f[maxn];
int pos[maxn][2];
void solve(){
int minv=INF,maxv=-INF;
int cnt1=0,cnt2=0;
for(int i=1;i<=N;i++){
if(a[i]<minv){
minv=a[i];
cnt1=1;
} else if(a[i]==minv){
cnt1++;
}
if(a[i]>maxv){
maxv=a[i];
cnt2=1;
} else if(a[i]==maxv){
cnt2++;
}
}
LL ans1=0,ans2=0;
if(maxv==minv){
ans1=(1LL*(N+1)*N/2)%MOD;
ans2=f[N]-1;
printf("%lld %lld\n",ans1,ans2);
return;
}
ans2=(f[N]-f[N-cnt1]-f[N-cnt2]+f[N-cnt1-cnt2])%MOD;
int pos1=-1,pos2=-1;
ans1=0;
for(int i=N;i>=1;i--){
if(a[i]==minv)pos1=i;
if(a[i]==maxv)pos2=i;
pos[i][0]=pos1,pos[i][1]=pos2;
}
for(int i=1;i<=N;i++){
if(pos[i][0]!=-1&&pos[i][1]!=-1){
int x=max(pos[i][0],pos[i][1]);
ans1+=N-(x-1);
if(ans1>=MOD)ans1-=MOD;
}
}
printf("%lld %lld\n",ans1,(ans2+MOD)%MOD);
}
int main(){
f[0]=1;
for(int i=1;i<maxn;i++){
f[i]=f[i-1]*2%MOD;
}
int T;
scanf("%d",&T);
while(T--){
scanf("%d",&N);
for(int i=1;i<=N;i++){
scanf("%d",&a[i]);
}
solve();
}
return 0;
}
I: http://acm.hust.edu.cn/vjudge/contest/view.action?cid=83690#problem/I
题意:每条龙都有一个生存周期,也会有一个父亲,问每条龙存在的时候,最多跟他的子孙隔多少代
思路:因为要查询他的子孙,所以首先对每个节点求出dfs序,隔多少代其实就是树中深度差多少,然后按照d(死亡时间)排序,离线处理,对于出生时间h小于d的都加进去,然后查询,具体看代码
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
typedef long long LL;
const int maxn=100010;
const int maxm=1010;
const int MOD=1e9+7;
const int INF=0x3f3f3f3f;
struct node{
int h,d,p,id;
node(){}
node(int _p,int _h,int _d,int _id):p(_p),h(_h),d(_d),id(_id){}
}a[maxn],b[maxn];
int dfn[maxn],dep[maxn],num[maxn];
int dfs_clock;
int N;
vector<int> G[maxn];
struct IntervalTree{
int maxv[maxn<<2];
void build(int o,int l,int r){
maxv[o]=0;
if(l==r){
return ;
}
int mid=(l+r)>>1;
build(o<<1,l,mid);
build(o<<1|1,mid+1,r);
}
void update(int o,int l,int r,int x,int val){
if(l==r){
maxv[o]=val;
return ;
}
int mid=(l+r)>>1;
if(x<=mid)update(o<<1,l,mid,x,val);
else update(o<<1|1,mid+1,r,x,val);
pushup(o);
}
void pushup(int o){
maxv[o]=max(maxv[o<<1],maxv[o<<1|1]);
}
int query(int o,int l,int r,int q1,int q2){
if(q1<=l&&r<=q2){
return maxv[o];
}
int ans=0;
int mid=(l+r)>>1;
if(q1<=mid)ans=max(ans,query(o<<1,l,mid,q1,q2));
if(q2>mid)ans=max(ans,query(o<<1|1,mid+1,r,q1,q2));
return ans;
}
}tree;
void dfs(int u,int depth){
dep[u]=depth;
num[u]=1;
dfn[u]=++dfs_clock;
int len=G[u].size();
for(int i=0;i<len;i++){
int v=G[u][i];
dfs(v,depth+1);
num[u]+=num[v];
}
}
bool cmp(node A,node B){
return A.h<B.h;
}
bool cmp1(node A,node B){
return A.d<B.d;
}
int ans[maxn];
int main(){freopen("in.txt","r",stdin);
int T;
scanf("%d",&T);
while(T--){
scanf("%d",&N);
for(int i=0;i<=N;i++){
G[i].clear();
}
for(int i=0;i<N;i++){
scanf("%d%d%d",&a[i].p,&a[i].h,&a[i].d);
a[i].id=b[i].id=i;
b[i].p=a[i].p;
b[i].h=a[i].h;
b[i].d=a[i].d;
if(a[i].p!=-1)G[a[i].p].push_back(i);
}
dfs_clock=0;
dfs(0,0);
sort(a,a+N,cmp);
sort(b,b+N,cmp1);
tree.build(1,1,N);
int j=0;
for(int i=0;i<N;i++){
while(j<N&&a[j].h<=b[i].d){
tree.update(1,1,N,dfn[a[j].id],dep[a[j].id]);
j++;
}
ans[b[i].id]=tree.query(1,1,N,dfn[b[i].id],dfn[b[i].id]+num[b[i].id]-1)-dep[b[i].id];
}
for(int i=0;i<N;i++){
printf("%d",ans[i]);
if(i==N-1)printf("\n");
else printf(" ");
}
}
return 0;
}
2015暑假训练(UVALive 5983 - 5992)线段树离线处理+dp的更多相关文章
- Codeforces Round #278 (Div. 1) Strip (线段树 二分 RMQ DP)
Strip time limit per test 1 second memory limit per test 256 megabytes input standard input output s ...
- 线段树+离线 hdu5654 xiaoxin and his watermelon candy
传送门:点击打开链接 题意:一个三元组假设满足j=i+1,k=j+1,ai<=aj<=ak,那么就好的.如今告诉你序列.然后Q次询问.每次询问一个区间[l,r],问区间里有多少个三元组满足 ...
- 牛客练习赛53 E-老瞎眼pk小鲜肉(思维+线段树+离线)
前言 听说是线段树离线查询?? 做题做着做着慢慢对离线操作有点感觉了,不过也还没参透,等再做些题目再来讨论离线.在线操作. 这题赛后看代码发现有人用的树状数组,$tql$.当然能用树状数组写的线段树也 ...
- 2015 多校联赛 ——HDU5316(线段树)
Fantasy magicians usually gain their ability through one of three usual methods: possessing it as an ...
- hdu 5475 模拟计算器乘除 (2015上海网赛H题 线段树)
给出有多少次操作 和MOD 初始值为1 操作1 y 表示乘上y操作2 y 表示除以第 y次操作乘的那个数 线段树的叶子结点i 表示 第i次操作乘的数 将1替换成y遇到操作2 就把第i个结点的值 替换成 ...
- UVaLive 11525 Permutation (线段树)
题意:有一个由1到k组成的序列,最小是1 2 … k,最大是 k k-1 … 1,给出n的计算方式,n = s0 * (k - 1)! + s1 * (k - 2)! +… + sk-1 * 0!, ...
- 玲珑oj 1117 线段树+离线+离散化,laz大法
1117 - RE:从零开始的异世界生活 Time Limit:1s Memory Limit:256MByte Submissions:438Solved:68 DESCRIPTION 486到了异 ...
- HDU 4638-Group(线段树+离线处理)
题意: 给n个编号,m个查询每个查询l,r,求下标区间[l,r]中能分成标号连续的组数(一组内的标号是连续的) 分析: 我们认为初始,每个标号为一个组(线段树维护区间组数),从左向右扫序列,当前标号, ...
- HDU 4630-No Pain No Game(线段树+离线处理)
题意: 给你n个数的序列a,q个询问,每个询问给l,r,求在下标i在[l,r]的区间任意两个数的最大公约数中的最大值 分析: 有了hdu3333经验,我们从左向右扫序列,如果当前数的约数在前面出现过, ...
随机推荐
- Codeforces Round #327 (Div. 2) B Rebranding(映射)
O(1)变换映射,最后一次性替换. #include<bits/stdc++.h> using namespace std; typedef long long ll; ; char s[ ...
- httpd2.4.6三种工作模式(如何配置),防止占用内存暴增的策略
之前偷懒默认用yum安装了httpd.后来发现服务器内存暴增,一度达到75% 打开一看,好嘛后台休眠进程全是httpd. 重启之后再度访问发现内存还是稳步增长. [root@iz2ze3ayxs2yp ...
- 【BZOJ1257】[CQOI2007] 余数之和(数学题)
点此看题面 大致题意: 求\(\sum_{i=1}^nk\%i\). 关于除法分块 这是一道除法分块的简单应用题. 式子转换 显然\(k\%i\)是一个很难处理的项. 于是我们就要使用使用一个常用的套 ...
- cuda api查询问题
在查询CUDA运行时API的时候,我用360极速浏览器的时候搜索结果一直不出来,但是用火狐的话就很流畅,所以建议大家在开发时还是用火狐浏览器.
- 10个HTML5 实战教程 提升你的综合开发能力
HTML5 作为下一代网站开发技术,无论你是一个 Web 开发人员或者想探索新的平台的游戏开发者,都值得去研究.借助尖端功能,技术和 API,HTML5 允许你创建响应性.创新性.互动性以及令人惊叹的 ...
- How to save console output to a file in Eclipse
https://coderanch.com/t/278299/java/Writing-output-console-file-system File file = new File("te ...
- java 代码优化
Java程序中的内存管理机制是通过GC完成的,“一个对象创建后被放置在JVM的堆内存中,当永远不在应用这个对象的时候将会被JVM在堆内存中回收.被创建的对象不能再生,同时也没有办法通过程序语句释放”( ...
- STMS传输队列中的请求状态一直是Running不能结束
通过STMS传输请求时,遇到了如下问题: STMS传输请求,不论等多久的时间,请求状态一直是running,不能结束.但检查传输的内容时,发现CHANGE REQUEST包含的内容已经传输到目标Cli ...
- WebService简单入门
写在前面的话: 当两个人碰面后,产生了好感,如果需要得到双方的信息,那么双方的交流是必不可少的!应用程序也如此, 各个应用程序之间的交流就需要WebService来作为相互交流的桥梁! 项目目的: 程 ...
- Python While循环、运算符以及一些基础运用
1.循环语句 循环打印"人生苦短,我用python" while True: print("人生苦短,我用python") 利用While循环,打印1~10 c ...