题解,java(6)

E - Mayor's posters
线段树
 引入:离散化
 将l,r储存在一个数组,排序去重,以l,r为导引在数组寻找值的位置,也就是映射
思路:线段树+离散化
离散化时需要进行 Hash[cnt++] = e[i].ri + 1; 不然出现单个数直接会直接覆盖
查询操作:遍历线段树所有结点,涂有颜色且未被访问过,答案++
 

#include 
#include
#include
#include
#define maxn 20005
using namespace std;
struct data{
    int le, ri;
}e[maxn];
int book[maxn << 3], Hash[maxn << 1], t[maxn << 3], cnt;
void pushdown(int rt){
    if (t[rt] != -1){
        t[rt << 1] = t[rt << 1 | 1] = t[rt];
        t[rt] = -1;
    }
}
void updata(int num, int l, int r, int L, int R, int rt){
    if (L >= l && R <= r){          //若在区间内染色
        t[rt] = num;
        return;
    }
    pushdown(rt);
    int m = (L + R) >> 1;
    if (l <= m)
        updata(num, l, r, L, m, rt << 1);
    if (r > m)
        updata(num, l, r, m + 1, R, rt << 1 | 1);
}
void query(int L, int R, int rt)
{
    if (t[rt] != -1){                //遍历线段树所有结点,涂有颜色且未被访问过,答案++
        if (!book[t[rt]]){
            cnt++;
            book[t[rt]] = 1;
        }
        return;           //已经一个结点涂有颜色,则区间涂有颜色,不需要遍历子节点
    }
    if (L == R)
        return;
    int m = (L + R) >> 1;
    query(L, m, rt << 1);
    query(m + 1, R, rt << 1 | 1);
}
int main()
{
    int T;
    scanf("%d", &T);
    while (T--)
    {
        int n;
        scanf("%d", &n);
        memset(book, 0, sizeof(book));
        memset(t, -1, sizeof(t));
        cnt = 1;
        for (int i = 0; i < n; i++)
        {
            scanf("%d%d", &e[i].le, &e[i].ri);
            Hash[cnt++] = e[i].le;
            Hash[cnt++] = e[i].ri;
            Hash[cnt++] = e[i].ri + 1;   //出现单个数直接会直接覆盖
        }
        sort(Hash + 1, Hash + cnt + 1);
        int len = unique(Hash + 1, Hash + cnt + 1) - Hash; 
        //unique函数将数组中相邻的重复元素去除。然而其本质是将重复的元素移动到数组的末尾,
        //最后再将迭代器指向第一个重复元素的下标。
        //len=去重后最后一个不重复元素的地址
        cnt = len;
        sort(Hash + 1, Hash + cnt + 1);
        len = cnt, cnt = 0;
        for (int i = 0; i < n; i++){
            int le = lower_bound(Hash, Hash + len, e[i].le) - Hash;   //查找第一个不小于e[i].len的地址
            int ri = lower_bound(Hash, Hash + len, e[i].ri) - Hash;
            updata(i, le, ri, 1, len, 1);   
        }
        query(1, len, 1); 
        printf("%d\n", cnt);   
    }
    return 0;
}

Codeforces Round 861 (Div. 2)
 Lucky Numbers
思路:100为一个循环,在i < 100&&(i+a)<=b前提下,寻找区间一个数中最大数-最小数的最大值的数即可

#include
using namespace std;
int arr[100];
int Find(int x) {
    int y = x;
    int Max = -1;
    int Min = 0x3f3f3f;
    while (y != 0) {
        int z = y % 10;
        y /= 10;
        if (z > Max)
            Max = z;
    }
    while (x != 0) {
        int z = x % 10;
        x /= 10;
        if (z < Min)
            Min = z;
    }
    return Max - Min;
}
int main()
{
    ios::sync_with_stdio(false);
    int t;
    cin >> t;
    while (t--) {
        int  a, b;
        cin >> a >> b;
        arr[0] = a;
        for (int i = 1; i < 100&&(i+a)<=b; i++) {
            arr[i] = a + i;
        }
        int Max = -1;
        int flag = 0;
        for (int i = 0; i < 100 && (i + a) <= b; i++) {
            int z = Find(arr[i]);
            if (z == 9) {
                flag = i;
                break;
            }
            if (z > Max) {
                flag = i;
                Max = Find(arr[i]);
            }
        }
        cout << arr[flag] << '\n';
    }
    return 0;
}


B. Playing in a Casino
错解:动态二维数组,时间超限

#include
#include
#include
using namespace std;
int main()
{
    ios::sync_with_stdio(false);
    int t;
    cin >> t;
    while (t--) {
        long long sum=0;
        int n, m;
        cin >> n >> m;
        vector > a(n+1, vector(m+1));
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= m; j++) {
                cin >> a[i][j];
            }
        }
        if (n == 1) {
            cout << "0\n";
            continue;
        }

        for (int i = 1; i <= n; i++) {
            for (int j = i + 1; j <= n; j++) {
                for (int k = 1; k <= m; k++) {
                    sum += abs(a[i][k] - a[j][k]);
                }
            }
        }
        cout << sum <<'\n';
    }
    return 0;
}
#include
#include
#include
#include
#include
using namespace std;
using LL = long long;
int main() {

    cin.tie(0);
    cout.tie(0);
    ios::sync_with_stdio(0);

    int T;
    cin >> T;
    while (T--) {
        int n, m;
        cin >> n >> m;
        vector > a(m);
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                int x;
                cin >> x;
                a[j].push_back(x);
            }
        }
        LL ans = 0;
        for (int i = 0; i < m; i++) {
            sort(a[i].begin(), a[i].end());
            LL sum = accumulate(a[i].begin(), a[i].end(), 0LL);
            LL pre = 0;
            for (int j = 0; j < n; j++) {
                ans += 1LL * j * a[i][j] - pre;
                pre += a[i][j];
                ans += sum - pre - 1LL * (n - j - 1) * a[i][j];
            }
        }
        cout << ans / 2 << '\n';
    }

}


思路:将每一行当作列存储,排序存储的行,
 考虑到绝对值和t题目中行行之间都会组合
sumi=b0+b1+...+bi得到存储的行值为i*bi-sumi相加,得到答案为行值相加
公式举例:c>b>a
|a-b|+|b-c|+|a-c|--->b-a+b+c-b+c-a--->2*c+b-2*a

#include
#include
#include
#include
#include
using namespace std;
using LL = long long;
int T, n, m;
LL work(vector& b)
{
    LL res = 0;
    int len = b.size();
    LL sum = 0;
    for (int i = 0; i < len; i++){
        res = res + (1LL * b[i] * i - sum);
        sum += b[i];
    }
    return res;
}
LL solve() {
    cin >> n >> m;
    vector > a(m, vector());
    int x;
    for (int i = 1; i <= n; i++) {
        for (int j = 0; j < m; j++) {    

            cin >> x;
            a[j].push_back(x);          //行当作列储存

        }
    }
        LL res = 0;
        for (int j = 0; j < m; j++) {
            sort(a[j].begin(), a[j].end());    //排序
            res += work(a[j]);
        }
        return res;
}
int main()
{
    cin.tie(0)->sync_with_stdio(false);
    cin >> T;
    while (T--){
        cout << solve() <<'\n';
    }
}

引入:高精度加减乘除及比较模板

#include 
#include 
using namespace std;
struct bign {
    int d[1000];
    int len;
    bign() {
        memset(d, 0, sizeof(d));
        len = 0;
    }
};
bign add(bign a, bign b) {
    bign c;
    int carry = 0;
    for (int i = 0; i < a.len || i < b.len; i++) {
        int t = a.d[i] + b.d[i] + carry;
        c.d[c.len++] = t % 10;
        carry = t / 10;
    }
    if (carry != 0) {
        c.d[c.len++] = carry;
    }
    return c;
}
bign sub(bign a, bign b) {
    bign c;
    for (int i = 0; i < a.len || i < b.len; i++) {
        if (a.d[i] < b.d[i]) {
            a.d[i + 1]--;
            a.d[i] += 10;
        }
        c.d[c.len++] = a.d[i] - b.d[i];
    }
    //去掉高位0
    while (c.len > 1 && c.d[c.len - 1] == 0) {
        c.len--;
    }
    return c;
}
bign mul(bign a, int b) {
    bign c;
    int carry = 0;
    for (int i = 0; i < a.len; i++) {
        int t = a.d[i] * b + carry;
        c.d[c.len++] = t % 10;
        carry = t / 10;
    }
    while (carry != 0) {
        c.d[c.len++] = carry % 10;
        carry /= 10;
    }
    return c;
}
bign div(bign a, int b) {
    bign c;
    int r = 0;
    c.len = a.len; //商的位数与除数一一对应,不够除为0
    for (int i = a.len - 1; i >= 0; i--) {
        int t = a.d[i] + r * 10;
        c.d[i] = t / b;
        r = t % b;
    }
    while (c.len > 1 && c.d[c.len - 1] == 0) {
        c.len--;
    }
    c.d[c.len] = r; //利用多余数组储存余数
    return c;
}
void print(bign a) {
    for (int i = a.len - 1; i >= 0; i--) {
        printf("%d", a.d[i]);
    }
}
int compare(bign a, bign b) {
    if (a.len > b.len) return 1;
    else if (a.len < b.len) return -1;
    else {
        for (int i = a.len - 1; i >= 0; i--) {
            if (a.d[i] > b.d[i]) return 1;
            else if (a.d[i] < b.d[i]) return -1;
        }
    }
    return 0;
}
int main() {
    int n;
    scanf("%d", &n);
    bign sum, a;
    a.d[0] = 1;
    a.len = 1;
    for (int i = 1; i <= n; i++) {
        a = mul(a, i);
        sum = add(sum, a);

    }
    print(sum);
    return 0;
}

Java

落实完面向对象,进入集合和泛型,了解Javafx使用

题解,java(6)_第1张图片

 

你可能感兴趣的:(java,算法,数据结构)