ZOJ Monthly, February 2012 C,D,F,H

C:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3573

瞎搞题,可以用线段树+lazy过。CB曾经出过一个类似的,可以0(N)的处理。左边加右边减,边走边算。

#include <algorithm>
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <iomanip>
#include <stdio.h>
#include <string>
#include <queue>
#include <cmath>
#include <stack>
#include <map>
#include <set>
#define eps 1e-8
#define M 1000100
#define LL long long
//#define LL long long
#define INF 0x3f3f3f
#define PI 3.1415926535898

const int maxn = 15100;

using namespace std;

LL f[maxn];
LL p[maxn];
LL k[maxn];

int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        int x, y, z;
        memset(f, 0, sizeof(f));
        memset(p, 0, sizeof(p));
        memset(k, 0, sizeof(k));
        while(~scanf("%d %d %d",&x, &y, &z))
        {
            if(x == -1) break;
            f[x] += z;
            p[y+1] -= z;
        }
        int lmax;
        LL Max = -1LL;
        LL xmax = 0LL;
        for(int i = 0; i <= n; i++)
        {
            xmax += f[i]+p[i];
            k[i] = xmax;
            if(xmax > Max)
            {
                Max = xmax;
                lmax = i;
            }
        }
        int rmax;
        for(int i = n; i >= 0; i--)
        {
            if(k[i] == Max)
            {
                rmax = i;
                break;
            }
        }
        cout<<lmax<<" "<<rmax<<endl;
    }
    return 0;
}

D:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3574

这道题目感觉挺好的,求在两个直线之间的所有线段的交点。一开始的想法是左右分别排序根据差值算出交点,但是排序好像有问题。后来改成按右边的y值排序再求出逆序数就可以了啊。

#include <algorithm>
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <iomanip>
#include <stdio.h>
#include <string>
#include <queue>
#include <cmath>
#include <stack>
#include <ctime>
#include <map>
#include <set>
#define eps 1e-12
///#define M 1000100
///#define LL __int64
#define LL long long
///#define INF 0x7ffffff
#define INF 0x3f3f3f3f
#define PI 3.1415926535898
#define zero(x) ((fabs(x)<eps)?0:x)

using namespace std;

const int maxn = 30100;

LL sum;

struct node
{
    LL y1;
    LL y2;
    int id;
};

node a[maxn], temp[maxn];
void Merge(node a[], int l, int mid, int r)
{
    int begin1 = l;
    int end1 = mid;
    int begin2 = mid+1;
    int end2 = r;
    int k = 0;
    while(begin1 <= end1 && begin2 <= end2)
    {
        if(a[begin1].y1 < a[begin2].y1)
        {
            temp[k++] = a[begin1];
            begin1++;
            sum += begin2-(mid+1);
        }
        else
        {
            temp[k++] = a[begin2];
            begin2++;
        }
    }
    while(begin1 <= end1)
    {
        temp[k++] = a[begin1];
        begin1++;
        sum += end2-mid;
    }
    while(begin2 <= end2)
    {
        temp[k++] = a[begin2];
        begin2++;
    }
    for(int i = l; i <= r; i++) a[i] = temp[i-l];
}

void MergeSort(node a[], int l, int r)
{
    int mid = (l+r)>>1;
    if(l < r)
    {
        MergeSort(a, l, mid);
        MergeSort(a, mid+1, r);
        Merge(a, l, mid, r);
    }
}

bool cmp(node a, node b)
{
    return a.y2 < b.y2;
}

int main()
{
    LL x1, x2;
    while(~scanf("%lld %lld",&x1, &x2))
    {
        int n;
        scanf("%d",&n);
        if(n == 0)
        {
            cout<<1<<endl;
            continue;
        }
        LL k, b;
        for(int i = 0; i < n; i++)
        {
            scanf("%lld %lld",&k, &b);
            a[i].y1 = k*x1+b;
            a[i].y2 = k*x2+b;
        }
        sort(a, a+n, cmp);
        sum = 0;
        MergeSort(a, 0, n-1);
        cout<<sum+n+1<<endl;
    }
    return 0;
}

F:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4598

这个题目是瞎猜了一下,把它转化为两个互质的模型后求出来百分比,用总的长度乘以百分比就可以了啊。

#include <algorithm>
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <iomanip>
#include <stdio.h>
#include <string>
#include <queue>
#include <cmath>
#include <stack>
#include <map>
#include <set>
#define eps 1e-8
#define M 1000100
#define LL long long
//#define LL long long
#define INF 0x3f3f3f
#define PI 3.1415926535898

const int maxn = 30010;

using namespace std;

int main()
{
    LL n, m;
    while(~scanf("%lld %lld",&n, &m))
    {
        double x = sqrt(n*n*1.0+m*m*1.0);
        LL p = __gcd(n, m);
        m /= p;
        n /= p;
        p = m*n;
        LL xx = p/2;
        if(p%2) xx++;
        double y = (xx*1.0)/p;
        printf("%.6lf\n",x*y);
    }
    return 0;
}

H:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3578

n很小可以暴力判断每次操作之后所在区域的最大值,然后加上h就是总的结果。最后求出一个最大值就可以了。

#include <algorithm>
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <iomanip>
#include <stdio.h>
#include <string>
#include <queue>
#include <cmath>
#include <stack>
#include <map>
#include <set>
#define eps 1e-8
#define M 1000100
#define LL long long
//#define LL long long
#define INF 0x3f3f3f
#define PI 3.1415926535898

const int maxn = 15100;

using namespace std;

struct node
{
    int h;
    int H;
    int a, b, x, y;
}f[maxn];

bool judge(int x, int y)
{
    if(f[x].x+f[x].a <= f[y].x || f[y].x+f[y].a <= f[x].x) return false;
    if(f[x].y+f[x].b <= f[y].y || f[y].y+f[y].b <= f[x].y) return false;
    return true;
}

int main()
{
    int n, m, c;
    while(~scanf("%d %d %d",&n, &m, &c))
    {
        for(int i = 0; i < c; i++)
        {
            scanf("%d %d %d %d %d",&f[i].a, &f[i].b, &f[i].h, &f[i].x, &f[i].y);
            f[i].H = 0;
            for(int k = 0; k < i; k++)
                if(judge(i, k)) f[i].H = max(f[i].H, f[k].H);
            f[i].H += f[i].h;
        }
        int Max = -1;
        for(int i = 0; i < c; i++) Max = max(Max, f[i].H);
        cout<<Max<<endl;
    }
    return 0;
}
时间: 2024-10-03 20:15:10

ZOJ Monthly, February 2012 C,D,F,H的相关文章

ZOJ Monthly,Feburary 2012 部分题解

题目链接:点击打开链接 ZOJ 3573 Under Attack 距离做这套题到写题解间隔比较久,题意有些忘了.. #include <iostream> #include <cstdio> #include <algorithm> #include <string> #include <cmath> #include <cstring> #include <queue> #include <set> #in

ZOJ Monthly, November 2012

A.ZOJ 3666 Alice and Bob 组合博弈,SG函数应用 #include<vector> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn = 10000 + 100; int SG[maxn]; vector<int> g[maxn]; int mex(int u) { //minimal exc

ZOJ Monthly, August 2012 题解

A: 题目链接:点击打开链接 Alice's present #include <cstdio> #include <iostream> #include <cstring> #include <string> #include <map> #include <queue> #include <set> #include <algorithm> using namespace std; int n, m; in

ZOJ Monthly, July 2012

zoj 3622.Magic Number   水题 先找规律生成区间[1,1<<32-1]内的所有Magic Number,计算出来只有40多个,然后就随便YY了. void init() { int a[5] = { 1,2,5,25,125 }; ll Max = (1ll<<32)-1; for(ll tmp =1; tmp<=Max; tmp *=10) { for(int i=0; i<5; ++i){ ll t = tmp * a[i]; if(t>

ZOJ 4009 And Another Data Structure Problem(ZOJ Monthly, March 2018 Problem F,发现循环节 + 线段树)

题目链接  ZOJ Monthly, March 2018 Problem F 题意很明确 这个模数很奇妙,在$[0, mod)$的所有数满足任意一个数立方$48$次对$mod$取模之后会回到本身. 所以开$48$棵线段树,和一个永久标记.当对某个区间操作时对这个区间加一层永久标记. 即当前我要查找的第$x$层,实际找的是第$up[i] + x$层. 时间复杂度$O(48nlogn)$ #include <bits/stdc++.h> using namespace std; #define

135 - ZOJ Monthly, August 2014

135 - ZOJ Monthly, August 2014 A:构造问题,推断序列奇偶性.非常easy发现最小值不是1就是0.最大值不是n就是n - 1,注意细节去构造就可以 E:dp.dp[i][j]表示长度i,末尾状态为j的最大值,然后每一个位置数字取与不取,不断状态转移就可以 G:就一个模拟题没什么好说的 H:dfs,每次dfs下去,把子树宽度保存下来,然后找最大值,假设有多个.就是最大值+cnt宽度 I:构造,假设r * 2 > R,肯定无法构造.剩下的就二分底边.按等腰三角形去构造就

记次浙大月赛 134 - ZOJ Monthly, June 2014

链接 虽做出的很少,也记录下来,留着以后来补..浙大题目质量还是很高的 B 并查集的一些操作,同类和不同类我是根据到根节点距离的奇偶判断的,删点是直接新加一个点,记得福大月赛也做过类似的,并差集的这类关系题目还是比较常见的,有空深究一下. 1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stdlib.h> 6

ZOJ Monthly, June 2014 解题报告

A.Another Recurrence Sequence B.Gears 题目大意:有n个齿轮,一开始各自为一组,之后进行m次操作,包括以下4种类型: 1.合并两组齿轮,合并的两个应该反向旋转 2.把某个齿轮从所在组删除,自为一组,但不影响同组其它齿轮的状态与关系 3.询问两个齿轮是同向.反向或无关系(即不在同一组) 4.询问某个齿轮所在组的齿轮总数 分析:典型的并查集操作,但是注意两点: 1.由于操作3要询问两个齿轮的相对状态,因此对并查集中每个元素应当保存它的状态信息.状态是相对的,只需要

ZOJ Monthly, September 2003【部分题解】

今天比赛做了一下这套题目.出了四道.两道水题,两道DP 比赛链接:http://vjudge.net/contest/view.action?cid=51404#problem/B 上来搞了一道水题之后就搞B题 题意很好理解,上来看了一下就懂了.以为是规律有循环节,没看wa那么多毅然决然提交,wa了一发. A = "^__^" and B = "T.T",C = BA = "T.T^__^".然后A=B,B=C,一直重复这个操作,问最后第n位的字