首页 > 其他分享 >codeforces 1575M Managing Telephone Poles

codeforces 1575M Managing Telephone Poles

时间:2024-02-24 19:22:07浏览次数:22  
标签:return Managing tr codeforces mid int maxn Poles const

假设固定了 \((x, y)\),考虑其和 \((x', y')\) 的距离 \((x - x')^2 + (y - y')^2 = x^2 - 2xx' + x'^2 + y^2 - 2yy' + y'^2 = (x^2 + y^2) + (-2xx' + x'^2) + (-2yy' + y'^2)\)。
第一个括号内的式子是个定值,不用管;第二三个式子都是一次函数的形式,但是这是个二元组,放在一起看很难处理。
于是考虑固定一边,比如固定下 \(x\),式子拆成 \(y^2 + (-2yy' + y'^2 + (x - x')^2)\),即把 \((x - x')^2\) 这个东西也当作一个定值加进一次函数。

但是看起来右边的括号会有 \(O(nm)\) 种情况还是优化不下去。
考虑去除掉不优的状态。
发现对于 \((x_1, y'), (x_2, y')\),如果 \(|x_1 - x| \le |x_2 - x|\),\((x_2, y')\) 这个点是无用的。
因为此时 \((y - y')^2\) 相同而固定下了 \(x\) 又有 \((x_1 - x)^2\le (x_2 - x)^2\),所以 \((x_1, y)\) 一定更优。
那么每个 \(y'\) 最多只会有一种情况,右边括号就只有 \(O(m)\) 种情况了。

时间复杂度 \(O(nm\log m)\)。

#include<bits/stdc++.h>
const int maxn = 2e3 + 10;
const int inf = INT_MAX;
int n, m;
char s[maxn][maxn];
int L[maxn][maxn], R[maxn][maxn];
struct seg {
    int k, b;
    int operator () (const int &x) {return k * x + b;}
} tr[maxn];
int ls[maxn], rs[maxn], tot, rt;
inline void insert(int &k, seg x, int l = 0, int r = m) {
    if (! k) {tr[k = ++tot] = x, ls[k] = rs[k] = 0; return ;}
    int mid = (l + r) >> 1;
    if (x(mid) < tr[k](mid)) std::swap(x, tr[k]);
    if (l == r) return ;
    if (x(l) < tr[k](l)) insert(ls[k], x, l, mid);
    if (x(r) < tr[k](r)) insert(rs[k], x, mid + 1, r);
}
inline int qry(int k, int x, int l = 0, int r = m) {
    if (! k) return inf;
    if (l == r) return tr[k](x);
    int mid = (l + r) >> 1;
    return std::min(tr[k](x), x <= mid ? qry(ls[k], x, l, mid) : qry(rs[k], x, mid + 1, r));
}
int main() {
    scanf("%d%d", &n, &m);
    for (int i = 0; i <= n; i++) scanf("%s", s[i]);
    for (int j = 0; j <= m; j++) {
        for (int i = 0, p = -1; i <= n; i++) s[i][j] == '1' && (p = i), L[i][j] = p;
        for (int i = n, p = -1; ~ i; i--) s[i][j] == '1' && (p = i), R[i][j] = p;
    }
    long long ans = 0;
    for (int i = 0; i <= n; i++) {
        rt = tot = 0;
        for (int j = 0; j <= m; j++) {
            int d = std::min(L[i][j] == -1 ? inf : (i - L[i][j]), R[i][j] == -1 ? inf : (R[i][j] - i));
            if (d == inf) continue;
            insert(rt, seg{-2 * j, d * d + j * j});
        }
        for (int j = 0; j <= m; j++) ans += j * j + qry(rt, j);
    }
    printf("%lld\n", ans);
    return 0;
}

标签:return,Managing,tr,codeforces,mid,int,maxn,Poles,const
From: https://www.cnblogs.com/rizynvu/p/18031452

相关文章

  • Educational Codeforces Round 162 (Rated for Div. 2)
    不会F的场。A答案是最左的\(1\)和最右的\(1\)之间的\(0\)的个数。Code#include<bits/stdc++.h>usingnamespacestd;usingll=longlong;intmain(){ ios::sync_with_stdio(false); cin.tie(0); intt; cin>>t; while(t--){ intn; cin>>n......
  • Educational Codeforces Round 162 [Rated for Div. 2]
    第二次,三道题,剩下的回学校再补,总结:还是需要多练习A:让数列里所有的1都挨在一起,可以看出,相邻1之间有多少个0就需要操作几次,特判:当只有一个1或者原本全是1就输出0;voidsolve(){cin>>n;inttop1=0,top2=0,cnt=0;memset(a,0,sizeof(a));memset(b,0,siz......
  • Codeforces 799E Aquarium decoration
    考虑去枚举能满足\(1,2\)的个数\(l\),那自然只能满足\(1\)或\(2\)的个数为\(\max\{k-l,0\}\)。对于还剩下的,可以从只能满足\(1,2\)和不能满足任意一个的选出来。显然如果要选就是选最小的。考虑用个数据结构优化这个过程。查询前\(k\)大的和,插入一个数,可以想......
  • Codeforces 图论题
    CF243BHydra枚举点\(u,v\),或者说枚举边。然后找出\(u,v\)分别所连的点。有数组\(st\),结点\(x\)仅与\(u\)相邻则\(st[x]=1\),仅与\(v\)相邻则\(st[x]=2\),与两个点都相邻则\(st[x]=3\)。用数组\(rest\)记录\(st[x]=3\)的所有\(x\)。先优先选走至多\(h\)个\(......
  • Codeforces 869D The Overdosing Ubiquity
    考虑树的\(\text{dfs}\)(根据当前节点\(u\)找到\(v\)满足存在\((u,v)\),然后走向\(v\)进入更深的搜索)为和能做到\(O(n)\)的复杂度。原因是没有环的情况,到每个点只有一条路径。回到这个题,有\(m\)条边导致到每个点可能有多条路径了。能发现其实还是能\(\text{dfs}\)......
  • Codeforces 1876F - Indefinite Clownfish
    首先注意到这样一个性质:既然两个序列的平均值相同,并且又形成公差\(\pm1\)的等差数列,就必然会存在一个元素\(x\)满足\(x\)在两个序列中都出现过(否则两个序列的值域区间不交,值域区间靠后的那个显然平均值比靠前的那个大)。那么我们枚举\(x\)在两个序列中出现的位置\(p\)和......
  • Codeforces Round 923 (Div. 3)
    A.MakeitWhite#include<bits/stdc++.h>usingnamespacestd;usingi32=int32_t;usingi64=longlong;usingi128=__int128;usingldb=longdouble;#defineinti64usingvi=vector<int>;usingpii=pair<int,int>;usingvii......
  • Codeforces Round 928 (Div. 4)
    CodeforcesRound928(Div.4)比赛链接A.VladandtheBestofFive思路就是统计字符A和字符B的个数,将个数多的那个输出出来Code#include<bits/stdc++.h>usingnamespacestd;#defineall(x)x.begin()+1,x.end()#defineintlonglongvoidsolve(){strings;......
  • Codeforces 1806E Tree Master
    考虑一个最基础的暴力,就是直接记忆化搜索暴力往上跳。但是能发现如果一层的节点数过多,状态数太多,就寄了。再考虑一个基础的暴力,就是直接跳。但是如果要跳的层数过多,就寄了。考虑结合一下,根号分治。对于一层内节点数\(\le\sqrt{n}\)的记录下每两个点间的答案。对于节点数......
  • Codeforces Round 928(Div. 4)
    Dashboard-CodeforcesRound928(Div.4)-Codeforces第一次参加CF,最后一道题连题都没读,下次不会就跳,菜是原罪A:找字符串中A,B数量,遍历一下最后比较即可B:判断是三角形还是正方形,题目表示除了正方形就是三角形,所以直接判断是不是正方形,用ans数组记录每一行1的个数,然后从大......