18.10.22 考试总结

我真的我要被我自己给猪死了md T1让输出边长我输出面积硬生生掉了100分 气死

这道题我之前在讲单调栈的时候是讲过的 对于每一个位置 维护一个他的$up$表示以这里为起点只走$1$向上走的高度

然后对于每一行都跑一边求最大矩形的单调栈即可 维护一个单增的 每次弹栈的时候求出以弹栈元素为矩形边长的最大矩形面积 不过这道题是求最大正方形

就改成边长取$min$再取$max$即可

代码

#include <bits/stdc++.h>
#define il inline
#define rg register
#define oo 1e9
using namespace std;

const int N = 2000 + 5;
int up[N][N], a[N][N], stk[N], n, m, top;

il int read( ) {

    int t = 1, ans = 0;
    char x; x = getchar( );
    while(x < ‘0‘ || x > ‘9‘) {
        if(x == ‘-‘) t = -1;
        x = getchar( );
    }
    while(x >= ‘0‘ && x <= ‘9‘) {
        ans = ans * 10 + x - ‘0‘;
        x = getchar( );
    }
    return ans * t;
}

il void Init( ) {

    n = read( ), m = read( );
    for(rg int i = 1;i <= n;i ++) {
        for(rg int j = 1;j <= m;j ++) {
            a[i][j] = read( );
            if(a[i][j] == 1) up[i][j] = up[i - 1][j] + 1;
            else up[i][j] = 0;
        }
        up[i][m + 1] = -oo;
    }
}

il void Solve( ) {

    int ans = 0;
    for(rg int i = 1;i <= n;i ++) {
        top = 0;
        for(rg int j = 1;j <= m + 1;j ++) {
            while(top && up[i][stk[top]] > up[i][j]) {
                ans = max(ans, min(up[i][stk[top]], j - 1 - stk[top - 1]));
                top --;
            }
            stk[++ top] = j;
        }
    }
    printf("%d\n", ans);
}

int main( ) {

    freopen("inspect.in", "r", stdin);
    freopen("inspect.out", "w", stdout);
    Init( );
    Solve( );
}

这道题其实是一道裸裸的而粪土二分图匹配

就对于每本书拆点 如果$a$能够摞到$b$上 就连接$a -> b$ 然后求一个最大匹配$cnt$即可 答案为$n - cnt$

因为每匹配一次相当于节省一个书架 注意判重 也就是如果两本书一模一样 就只需要连一条就够了 否则会减多

代码

#include <bits/stdc++.h>
#define il inline
#define rg register
#define oo 1e9
using namespace std;

const int N = 300 + 5;
int src, sink, x[N], y[N], tot, head[2 * N];
int nex[N * N], tov[N * N], n;
int cx[2 * N], cy[2 * N], ans = 0;
bool vis[2 * N];

il int read( ) {

    int t = 1, ans = 0;
    char x; x = getchar( );
    while(x < ‘0‘ || x > ‘9‘) {
        if(x == ‘-‘) t = -1;
        x = getchar( );
    }
    while(x >= ‘0‘ && x <= ‘9‘) {
        ans = ans * 10 + x - ‘0‘;
        x = getchar( );
    }
    return ans * t;
}

il void add(int u, int v) {

    tot ++; nex[tot] = head[u];
    tov[tot] = v; head[u] = tot;
}

il void Add_Edge( ) {

    n = read( );
    for(rg int i = 1;i <= n;i ++) x[i] = read( ), y[i] = read( );
    for(rg int i = 1;i <= n;i ++) {
        for(rg int j = 1;j <= n;j ++) {
            if(i == j) continue;
            if(x[j] == x[i] && y[j] == y[i]) {
                if(i < j) add(i, j + n); continue;
            }
            if(x[j] >= x[i] && y[j] >= y[i]) add(i, j + n);
        }
    }
}

il int dfs(int u) {

    for(rg int i = head[u];i;i = nex[i]) {
        int v = tov[i];
        if(vis[v]) continue;
        vis[v] = true;
        if(! cy[v] || dfs(cy[v])) {
            cy[v] = u; cx[u] = v;
            return 1;
        }
    }
    return 0;
} 

int main( ) {

    freopen("militarytraining.in", "r", stdin);
    freopen("militarytraining.out", "w", stdout);
    Add_Edge( );
    for(int i = 1;i <= n;i ++)
        if(! cx[i]) {
            memset(vis, 0, sizeof(vis));
            ans += dfs(i);
        }
    printf("%d\n", n - ans);
}

这道题我暴力莫队70分hhh

正解是将询问离线 按照左端点排序 然后要做的事情是在从后往前扫的过程中 求出每个数产生贡献的区间 用前缀和查分对于以当前点为左端点的区间的答案

维护一个数组$t,t[i]$ 表示如果询问区间包含了点$i$ 答案会增加$t[i]$(可能为负)

初始情况下$t$全为$0$,$i$从$n$枚举到$1$

对某个$i$  考虑$a[i]$这个数在$i$位置及其以后是否出现过$a[i]$次及以上 假设$a[i]$在位置$x$出现了第$a[i]$次 在位置y出现了第$a[i]+1$次

即表示对于左端点为$i$的询问区间 当右端点在$[x,y)$时 $a[i]$会贡献$1$的答案 否则贡献$0$的答案 此时设$t[x]=1$且$t[y] = -1$即可

用一个树状数组维护$t$数组,可以很容易的统计前缀和。

复杂度为$O(nlogn+qlogn+qlogq)$

代码

#include <bits/stdc++.h>
using namespace std;

const int N = 1e6 + 5;
int c[N], t[N], cnt[N], n, q, a[N], ans[N];
vector<int>pos[N];

struct ques {
    int id, l, r;
}Q[N];

bool cmp(const ques & a, const ques & b) {
    return a.l < b.l;
}

int read( ) {

    int t = 1, ans = 0;
    char x; x = getchar( );
    while(x < ‘0‘ || x > ‘9‘) {
        if(x == ‘-‘) t = -1;
        x = getchar( );
    }
    while(x >= ‘0‘ && x <= ‘9‘) {
        ans = ans * 10 + x - ‘0‘;
        x = getchar( );
    }
    return ans * t;
}

void Init( ) {

    n = read( ), q = read( );
    for(int i = 1;i <= n;i ++) a[i] = read( );
    for(int i = 1;i <= q;i ++) {
        Q[i].l = read( ), Q[i].r = read( ); Q[i].id = i;
    }
    sort(Q + 1, Q + q + 1, cmp);
}

int lowbit(int x) {
    return x & (-x);
}

int query(int pos) {

    int ans = 0;
    while(pos >= 1) {
        ans += c[pos];
        pos -= lowbit(pos);
    }
    return ans;
}

void modify(int pos, int del) {

    while(pos < N) {
        c[pos] += del;
        pos += lowbit(pos);
    }
}

void update(int x) {

    t[a[x]] ++; pos[a[x]].push_back(x);
    if(t[a[x]] == a[x]) modify(pos[a[x]][0], 1);
    else if(t[a[x]] == a[x] + 1) {
        modify(pos[a[x]][0], -1);
        int pos1 = pos[a[x]][cnt[a[x]] ++], pos2 = pos[a[x]][cnt[a[x]]];
        modify(pos1, -1);int cc = query(N);
        modify(pos2, 1);
    }
    else if(t[a[x]] > a[x] + 1) {
        int pos1 = pos[a[x]][cnt[a[x]] - 1], pos2 = pos[a[x]][cnt[a[x]] ++], pos3 = pos[a[x]][cnt[a[x]]];
        modify(pos1, 1);
        modify(pos2, -2);
        modify(pos3, 1);
    }
}

void Solve( ) {

    int now = q;
    for(int i = n;i >= 1;i --) {
        update(i); int cc = query(14);
        while(Q[now].l == i) {
            ans[Q[now].id] = query(Q[now].r); now --;
        }
    }
    for(int i = 1;i <= q;i ++) printf("%d\n", ans[i]);
}

int main( ) {

    freopen("count.in", "r", stdin);
    freopen("count.out", "w", stdout);
    Init( );
    Solve( );
}

原文地址:https://www.cnblogs.com/Rubenisveryhandsome/p/9831125.html

时间: 2024-10-08 07:14:44

18.10.22 考试总结的相关文章

18.9.22 考试总结

这道题一看就是可持久化并查集 然后我就愉快的yy了一波 还是错掉了qwqwqwqwq 方法是对的 就是我每次在树上查询$fa$的时候我还压缩了路径 导致这玩意空间炸掉了 所以要保证时间复杂度 就启发式合并 也就是$size$小的往$size$大的搞 这样子就保证每次合并的时候连通块元素个数每次至少乘以$2$ 也就是保证了层数是$log$级的 代码 #include <bits/stdc++.h> using namespace std; const int N = 1e5 + 5; int n

18.10.17 考试总结

今天心态崩崩,,,.. 这道题比较简单 因为每一位是单独对答案产生贡献的 所以枚举每一位 用数位dp求出该位是$1$的数量 在求出该位是$0$的 那么答案就是那一位对应的二的幂次再乘以$num1 * num0 * 2$ 每一对会产生两次贡献 代码 #include <bits/stdc++.h> #define rg register #define il inline using namespace std; typedef long long ll; const ll MOD = 1e9

18.10.4 考试总结

这道题就是一道肥!肠!裸!的!轮廓线dp 然后因为细节太多了还因为有一个sbsbsb编译错误 就是不准我函数名字取count...我恨 我永远讨厌轮廓线dp 代码 #include <bits/stdc++.h> using namespace std; const int N = 1e6 + 5; int dp[2][N],n,m,len[200],cnt[N],ans; char s[200][40]; void Init( ) { scanf("%d%d",&

18.10.6 考试总结

这道题就是一道模拟题 也没有什么细节 反正蛮好写的 代码 #include <bits/stdc++.h> using namespace std; const int N = 1005; int hx, hy, lx, ly, now, ma, h; int vis[2 * N][2 * N], T; char opt[105]; void deal(int sta, char opt, int del) { if(sta == 1) { if(opt == 'E' || opt == 'W

Daily Scrum 10.22

(写于10.22周四0晨) 昨天任务还未完成的继续完成任务. 每个人都查看自己的TFS,修改已经完成的任务状态,改为已关闭-已完成. 由于android studio运行过于慢,我们统一采取eclipse. 按照目前的进度,大家今天上午将环境都配好,目前的配置是: ADT:按照康家华给的版本配置 SDK:manager统一装4.0.3,在eclipse的路径选择中也选4.0.3 Eclipse:Luna 康家华和马瑶华继续昨天未完成的UI的工作,自定义的部分可以稍微放一下,主要框架先出来. 张启

2014年4月23日 10:22:08

step 1 : 做tcp网络编程,要解析一批批的数据,可是数据是通过Socket连接的InputStream一次次读取的,读取到的不是需要转换的对象,而是要直接根据字节流和协议来生成自己的数据对象. 按照之前的编程思维,总是请求然后响应,当然Socket也是请求和响应,不过与单纯的请求响应是不同的. 这里Socket连接往往是要保持住的,也就是长连接,然后设置一个缓冲区,网络流不断的追加到缓冲区.然后后台去解析缓冲区的字节流. http://cuisuqiang.iteye.com/blog/

[CareerCup] 18.10 Word Transform 单词转换

18.10 Given two words of equal length that are in a dictionary, write a method to transform one word into another word by changing only one letter at a time. The new word you get in each step must be in the dictionary. 这道题让我们将一个单词转换成另一个单词,每次只能改变一个字母,

18.6 负载均衡集群介绍;18.7 LVS介绍;18.9 LVS NAT模式搭建(上);18.10 LVS NAT模式搭建(下)

扩展: lvs 三种模式详解 http://www.it165.net/admin/html/201401/2248.html lvs几种算法 http://www.aminglinux.com/bbs/thread-7407-1-1.html 关于arp_ignore和 arp_announce http://www.cnblogs.com/lgfeng/archive/2012/10/16/2726308.html lvs原理相关的   http://blog.csdn.net/pi9nc/

18.6 负载均衡集群介绍 18.7 LVS介绍 18.8 LVS调度算法 18.9/18.10 L

18.6 负载均衡集群介绍18.7 LVS介绍 18.8 LVS调度算法 18.9/18.10 LVS NAT模式搭建 原文地址:http://blog.51cto.com/13227377/2149682