• [POI2011]MET-Meteors


    ( ext{Problem})

    [POI2011]MET-Meteors

    ( ext{Analysis})

    为方便操作,我们把长度为 (m) 的环倍长,把修改 (l < r)(r) 改为 (r+m)
    而后就可以整体二分了
    二分答案,把需要的修改放到树状数组,检查询问时一个一个枚举其所在位置,相应划分询问,继续二分

    ( ext{Code})

    #include<cstdio>
    #define LL long long
    using namespace std;
    
    const int N = 3e5 + 5;
    int n, m, cnt, p[N], h[N], ans[N];
    
    struct node{
    	int ty, l, r, a, id;
    }q[N * 2], q1[N * 2], q2[N * 2];
    
    struct edge{
    	int to, nxt;
    }e[N];
    
    inline void read(int &x)
    {
    	x = 0; char ch = getchar();
    	while (ch < '0' || ch > '9') ch = getchar();
    	while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
    }
    
    inline void link(int x, int y)
    {
    	static int tot = 0;
    	e[++tot] = edge{y, h[x]}, h[x] = tot;
    }
    
    LL c[N * 2];
    inline int lowbit(int x){return  x & (-x);}
    inline void add(int x, int v){for(; x <= 2 * m; x += lowbit(x)) c[x] += v;}
    inline LL query(int x)
    {
    	LL ret = 0;
    	for(; x; x -= lowbit(x)) ret += c[x];
    	return ret;
    }
    
    void solve(int l, int r, int ql, int qr)
    {
    	if (ql > qr) return;
    	if (l == r)
    	{
    		for(int i = ql; i <= qr; i++)
    		if (!q[i].ty) ans[q[i].l] = l;
    		return;
    	}
    	int mid = (l + r) >> 1, cnt1 = 0, cnt2 = 0;
    	for(int i = ql; i <= qr; i++)
    	{
    		if (q[i].ty == 1)
    		{
    			if (q[i].id <= mid) add(q[i].l, q[i].a), add(q[i].r + 1, -q[i].a), q1[++cnt1] = q[i];
    			else q2[++cnt2] = q[i];
    		}
    		else{
    			LL sum = 0;
    			for(int j = h[q[i].l]; j; j = e[j].nxt)
    			{
    				sum += query(e[j].to) + query(e[j].to + m);
    				if (sum >= q[i].r)
    				{
    					q1[++cnt1] = q[i];
    					break;
    				}
    			}
    			if (sum < q[i].r) q[i].r -= sum, q2[++cnt2] = q[i];
    		}
    	}
    	for(int i = 1; i <= cnt1; i++)
    	if (q1[i].ty == 1) add(q1[i].l, -q1[i].a), add(q1[i].r + 1, q1[i].a);
    	for(int i = 1; i <= cnt1; i++) q[ql + i - 1] = q1[i];
    	for(int i = 1; i <= cnt2; i++) q[ql + cnt1 + i - 1] = q2[i];
    	solve(l, mid, ql, ql + cnt1 - 1), solve(mid + 1, r, ql + cnt1, qr);
    }
    
    int main()
    {
    	read(n), read(m);
    	for(int i = 1, x; i <= m; i++) read(x), link(x, i);
    	for(int i = 1; i <= n; i++) read(p[i]);
    	int k; read(k);
    	for(int i = 1, l, r, a; i <= k; i++) 
    	{
    		read(l), read(r), read(a);
    		if (l > r) r += m;
    		q[++cnt] = node{1, l, r, a, i};
    	}
    	for(int i = 1; i <= n; i++) q[++cnt] = node{0, i, p[i]};
    	solve(1, k + 1, 1, cnt);
    	for(int i = 1; i <= n; i++)
    	{
    		if (ans[i] != k + 1) printf("%d
    ", ans[i]);
    		else printf("NIE
    ");
    	}
    }
    
  • 相关阅读:
    [NoiPlus2016]天天爱跑步
    POJ3539 Elevator
    CodeForces 37E Trial for Chief
    CodeForces 986C AND Graph
    [tyvj-2054][Nescafé29]四叶草魔杖 费用流
    [CodeForces]986A Fair
    [CodeForces]981C Useful Decomposition
    分配问题
    圆桌问题
    数字梯形问题
  • 原文地址:https://www.cnblogs.com/leiyuanze/p/14970685.html
Copyright © 2020-2023  润新知