MiYu原创, 转帖请注明 : 转载自 ______________白白の屋
题目地址:
http://acm.hdu.edu.cn/showproblem.php?pid=2795
题目描述:
3 5 5 2 4 3 3 3
1 2 1 3 -1
一开始没想明白怎么做 , 仔细想了想, 再次 读题后 发现 , n <= 200000; 也就是说 最多 也就 200000 条广告 , 你就算每行贴一张 ,
最多也就贴到 200000 行, 所以 不要被 h <= 10^9 次方吓到了 ,认为 线段树开不了那么大的数组 . 只要开 200000 就可以了 .
其他的 没什么 好说的 , 知道这个 就直接 暴 吧 ............将近 7000MS .=水过................. g++提交 还华丽的 送出了 一次 TLE....
C++ 水过了 ............
// 一直没明白 为什么我的 代码速度 那么 慢, 查询后 更新 的时间是 2000MS 左右 , 我的 是 查询 就更新了,
竟然要 将近 7000MS ? 非常 郁闷 , 不信邪的 继续 检查 代码, 在 瞪了 1哥小时后 , 忽然想到 : 把 cout 改成
printf 会怎样? 结果 : 1640 MS AC ..............鬼知道他的 数据量有多大..... cout 和 printf
竟然 差了 5000 MS 的时间 ...........无语
代码如下 :
/*
Coded By : MiYu
Link : http://www.cnblogs.com/MiYu || http://www.cppblog.com/MiYu
Author By : MiYu
Test : 1
Program : 2795
*/
//#pragma warning( disable:4789 )
#include <iostream>
#include <algorithm>
#include <string>
#include <set>
#include <map>
#include <utility>
#include <queue>
#include <stack>
#include <list>
#include <vector>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
using namespace std;
struct ADV {
int left, right, val;
int mid () { return ( left + right ) >> 1; }
}adv[800000];
int N, W, H, w;
void creat ( int l, int r, int rt = 1 ){
adv[rt].left = l;
adv[rt].right = r;
adv[rt].val = W;
if ( l == r )
return ;
int mid = adv[rt].mid();
creat ( l, mid, rt << 1 );
creat ( mid + 1, r, ( rt << 1 ) + 1 );
}
void add ( int rt = 1, int wei = w ){
if ( wei <= adv[rt].val ){
if ( adv[rt].left == adv[rt].right ){
adv[rt].val -= wei;
//cout << adv[rt].left << endl; //杯具的 地方
printf ( "%d\n", adv[rt].left );
return ;
} else if ( adv[rt<<1].val >= wei ) {
add ( rt << 1 );
adv[rt].val = max ( adv[rt<<1].val, adv[(rt<<1)+1].val );
} else {
add ( ( rt << 1 ) + 1 );
adv[rt].val = max ( adv[rt<<1].val, adv[(rt<<1)+1].val );
}
} else {
//cout << -1 << endl; //杯具的地方
puts ( "-1" );
}
}
inline bool scan_ud(int &num)
{
char in;
in=getchar();
if(in==EOF) return false;
while(in<'0'||in>'9') in=getchar();
num=in-'0';
while(in=getchar(),in>='0'&&in<='9'){
num*=10,num+=in-'0';
}
return true;
}
int main ()
{
while ( scan_ud (H)&&scan_ud (W)&&scan_ud (N) ) {
if ( H > 200000 )
H = 200010;
creat ( 1, H );
for ( int i = 1; i <= N; ++ i ) {
scan_ud (w);
add ( );
}
}
return 0;
}
另 附上 傻崽 神牛 代码 :
#include <iostream>
#include <algorithm>
#include <string>
#include <set>
#include <map>
#include <utility>
#include <queue>
#include <stack>
#include <list>
#include <vector>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#define FF(i,a) for( int i = 0 ; i < a ; i ++ )
#define FOR(i,a,b) for( int i = a ; i < b ; i ++ )
#define LL(a) a<<1
#define RR(a) a<<1|1
template<class T> inline void checkmin(T &a,T b) {if(a < 0 || a > b)a = b;}
template<class T> inline void checkmax(T &a,T b) {if(a < b) a = b;}
using namespace std;
struct Node {
int val;
int idx;
friend bool operator < (Node a , Node b) {
if(a.val == b.val) {
return a.idx > b.idx;
}
return a.val < b.val;
}
}error;
struct Seg_Tree{
int left,right;
Node node;
int mid() {
return (left + right)>>1;
}
}tt[800000];
int n , h , m;
void build(int l,int r,int idx) {
tt[idx].left = l;
tt[idx].right = r;
tt[idx].node.idx = l;
tt[idx].node.val = h;
if(l == r) return ;
int mid = tt[idx].mid();
build(l,mid,LL(idx));
build(mid+1,r,RR(idx));
}
void update(int l,int r,int val,int idx) {
if(l <= tt[idx].left && r >= tt[idx].right) {
tt[idx].node.val += val;
return ;
}
int mid = tt[idx].mid();
if(l <= mid) update(l,r,val,LL(idx));
if(mid < r) update(l,r,val,RR(idx));
tt[idx].node = max(tt[LL(idx)].node,tt[RR(idx)].node);
}
Node query(int w,int idx) {
if(tt[idx].node.val < w) {
return error;
}
if(tt[idx].left == tt[idx].right) {
return tt[idx].node;
}
if(tt[LL(idx)].node.val >= w) {
return query(w,LL(idx));
} else {
return query(w,RR(idx));
}
}
int main() {
error.idx = -1;
while(scanf("%d%d%d",&n,&h,&m) == 3) {
checkmin(n,m);
build(1,n,1);
while(m --) {
int w;
scanf("%d",&w);
Node ret = query(w,1);
printf("%d\n",ret.idx);
if(ret.idx != -1) {
update(ret.idx,ret.idx,-w,1);
}
}
}
return 0;
}