多校补题2

第6场
05 05 05 Snowy Smile
赛场上队友上来就开这道题敲的特high,敲完后 T T T了好几发,还在说自己复杂度正确。。。最后不 T T T了一直 W A WA WA
我和另外一个队友在搞 02 02 02,因为感觉可以可以做,但是整个下午都没怼过,思路也不对。。
这道题不是很难,思路是枚举矩形的左下端点和右上端点,用线段树维护矩形内的纵坐标方向的最大子段和,这样就可以在log的复杂度内找到一个矩形的权值最大的"连续纵坐标方向的子矩形"了。。如图,红色矩形就是"连续纵坐标方向的子矩形"。

代码参考了 c l a r i s claris claris的标程,学到一些技巧。。 c l a r i s N B ! claris NB! clarisNB!

#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
#define ft first
#define sd second
#define all(c) ((c).begin()), ((c).end())
#define mp(a, b) make_pair(a, b)
#define pb(x) push_back(x)
template<typename T>T gcd(T a, T b) {return b==0?a:gcd(b, a%b);}
#ifndef ONLINE_JUDGE
#define debug(fmt, ...) {printf("debug ");printf(fmt,##__VA_ARGS__);puts("");}
#else
#define debug(fmt, ...)
#endif
const int maxn = 1e5+5;
typedef long long ll;
const ll mod = 1e9+7;
int Case = 1;
int n, m;
ll ms[maxn<<2], ls[maxn<<2], rs[maxn<<2], sum[maxn<<2];
int pos[maxn];
void pushup(int rt) {
    ls[rt] = max(ls[rt<<1], sum[rt<<1]+ls[rt<<1|1]);
    rs[rt]=max(rs[rt<<1|1], sum[rt<<1|1] + rs[rt<<1]);
    sum[rt]=sum[rt<<1] + sum[rt<<1|1];
    ms[rt]=max(max(ms[rt<<1], ms[rt<<1|1]), rs[rt<<1] + ls[rt<<1|1]);
}
void build(int rt, int l, int r) {
    sum[rt] = ms[rt] = ls[rt] = rs[rt] = 0;
    if(l == r) {pos[l] = rt;return;}
    int mid = (l+r)/2;
    build(rt<<1, l, mid);
    build(rt<<1|1, mid+1, r);
}
void update(int rt, int val) {
    sum[rt]+=val;
    if(sum[rt]>0)ls[rt] = rs[rt] = ms[rt] = sum[rt];
    else ls[rt] = rs[rt] = ms[rt] = 0;
    for(rt>>=1; rt; rt>>=1) {
        pushup(rt);
    }
}
struct node{int x, y, z;bool operator<(const node s)const{return x < s.x;}}cc[maxn];
vector<int>ve;
int getid(int x) {
    return lower_bound(all(ve), x)-ve.begin()+1;
}
void solve() {
    cin>>n;ve.clear();
    for(int i = 1; i <= n; i++) {
        cin>>cc[i].x>>cc[i].y>>cc[i].z;
        ve.pb(cc[i].y);
    }
    sort(all(ve));ve.erase(unique(all(ve)), ve.end());
    sort(cc+1, cc+1+n);
    m = ve.size();ll res = 0;
    for(int i = 1; i <= n; i++) cc[i].y = getid(cc[i].y);
    for(int i = 1; i <= n; i++) {
        if(i == 1 || cc[i].x != cc[i-1].x) {
            build(1, 1, m);int k;
            for(int j = i; j <= n; j = k) {
                for(k = j; k <= n && cc[k].x == cc[j].x; k++) update(pos[cc[k].y], cc[k].z);
                res = max(res, ms[1]);
            }
        }
    }
    cout<<res<<endl;
    return;
}
int main() {
    ios::sync_with_stdio(false);cin.tie(0);std::cout.tie(0);
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
    //freopen("out.txt","w",stdout);
#endif
    //scanf("%d", &Case);
    cin>>Case;
    while(Case--) {
        solve();
    }
    return 0;
}

某左队友。。感觉多校在打假赛

全部评论

相关推荐

HR_丸山彩同学:你的项目描述里,系统设计讲了很多:MemCube是什么、三级存储架构怎么设计、四种遗忘策略分别是什么。这些面试的时候讲没问题,但简历上不需要这么细。 简历要突出的是影响力,不是实现细节。面试官看简历的时候想知道的是「这个项目有多大价值」,不是「这个项目具体怎么实现的」。实现细节是面试时候聊的 怎么改:技术细节可以精简为一句「采用三级存储架构+四种遗忘策略」,把省出来的篇幅用来写影响力。比如:项目有没有开源?有没有写成技术博客?有没有被别人使用过? 校园经历没有任何信息量,任何人都可以写这句话,写了等于没写。更关键的是,你投的是技术岗,校园活动经历本来就不是加分项。如果非要写,必须写出具体的数字和成果。如果你没有这些数字,那就老老实实删掉 「端到端耗时缩减30-40%」要给出确切数字和绝对值。从1000ms降到600ms是降了40%,从100ms降到60ms也是降了40%,但这两个含义完全不一样。其他也是,涉及到数据,准备好证据,口径统一,面试会问 「熟练」「熟悉」「了解」混在一起用,读起来很乱。而且「了解前端需求」最好改成「具备前后端协作经验」
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务