• CodeForces


    题目链接

    题目大意

      给出n个人,每个人都有一个能力值。然后公司每年会把能力值最低的几个人换掉,然后还有q个修改方案,修改方案会修改之前替换的能力值,问原来n个人中的第一个人是否会被t掉。

    解题思路

      首先需要统计出未修改时上次替换之后还有多少人的能力值比第一个人小,然后将其与现在需要替换的人数相减,如果值小于0的话,那么第一个人就会被裁掉(这里的负数是有意义的,这个负数代表了之前必须有多少个原来比第一个人能力值变的比他小才能使第一个人不会被裁掉,注意到这点的话这题基本就能解出来了)。然后对于每次修改,如果修改的这个值比第一个人的能力值大(小),而修改前比他小(大),那么修改以后的年份都会受影响,修改之后判断一下是否出现负数就行了。可以用线段树来维护这个过程。

    代码

    const int maxn = 1e5+10;
    const int maxm = 2e5+10;
    int a[maxn], les[maxn];
    vector<int> b[maxn];
    struct N {
    	int minn, lz;
    } tree[maxn<<2];
    inline void push_up(int rt) {
    	tree[rt].minn = min(tree[rt<<1].minn, tree[rt<<1|1].minn);
    }
    inline void push_down(int rt) {
    	if (tree[rt].lz) {
    		int lz = tree[rt].lz;
    		N &ls = tree[rt<<1];
    		N &rs = tree[rt<<1|1];
    		ls.lz += lz, rs.lz += lz;
    		ls.minn += lz, rs.minn += lz;
    		tree[rt].lz = 0;
    	}
    }
    void build(int rt, int l, int r) {
    	if (l==r) {
    		tree[rt].minn = les[l];
    		return;
    	}
    	int mid = (l+r)>>1;
    	build(rt<<1, l, mid);
    	build(rt<<1|1, mid+1, r);
    	push_up(rt);
    }
    void update(int rt, int l, int r, int a, int b, int val) {
    	if (l>=a && r<=b) {
    		tree[rt].lz += val;
    		tree[rt].minn += val;
    		return;
    	}
    	push_down(rt);
    	int mid = (l+r)>>1;
    	if (a<=mid) update(rt<<1, l, mid, a, b, val);
    	if (b>mid) update(rt<<1|1, mid+1, r, a, b, val);
    	push_up(rt);
    }
    int main() {	
    	int n, m, q; cin >> n >> m >> q;
    	for (int i = 1; i<=n; ++i) scanf("%d", &a[i]);
    	for (int i = 1, k; i<=m; ++i) {
    		scanf("%d", &k); b[i].push_back(0);
    		for (int j = 1, num; j<=k; ++j) {
    			scanf("%d", &num);
    			b[i].push_back(num);
    		}
    	}
    	int x, y, z;
    	for (int i = 2; i<=n; ++i)
    		if (a[i]<a[1]) ++les[0];
    	les[1] = les[0];
    	for (int i = 1; i<=m; ++i) {
    		les[i+1] = les[i];
    		les[i] -= b[i].size()-1;
    		for (int j = 1; j<b[i].size(); ++j)
    			if (b[i][j]>a[1]) --les[i+1];
    		//cout << les[i] << endl;
    	}
    	build(1, 1, m);
    	while(q--) {
    		scanf("%d%d%d", &x, &y, &z);
    		if (x!=m && b[x][y]>a[1] && z<a[1]) update(1, 1, m, x+1, m, 1);
    		else if (x!=m && b[x][y]<a[1] && z>a[1]) update(1, 1, m, x+1, m, -1);
    		b[x][y] = z;
    		printf("%d
    ", tree[1].minn>=0);
    	}
    	return 0;
    } 
    
  • 相关阅读:
    Junit单元测试
    win7的6个网络命令
    WOJ1024 (POJ1985+POJ2631) Exploration 树/BFS
    WOJ1022 Competition of Programming 贪心 WOJ1023 Division dp
    woj1019 Curriculum Schedule 输入输出 woj1020 Adjacent Difference 排序
    woj1018(HDU4384)KING KONG 循环群
    woj1016 cherry blossom woj1017 Billiard ball 几何
    woj1013 Barcelet 字符串 woj1014 Doraemon's Flashlight 几何
    woj1012 Thingk and Count DP好题
    woj1010 alternate sum 数学 woj1011 Finding Teamates 数学
  • 原文地址:https://www.cnblogs.com/shuitiangong/p/14466097.html
Copyright © 2020-2023  润新知