• 【Luogu P2824】[HEOI2016/TJOI2016]排序


    题目大意:

    给出一个 (1)(n) 的排列,(m) 次操作让某区间升序排或降序排,问 (q) 位置最后是多少。

    正文:

    本题十分巧妙,二分一个 (k),排列里大于 (k) 的数为 1,否则为 0,线段树维护这个 01串,进行排序,再根据 (q) 的位置调整二分范围。

    代码:

    
    struct SegmentTree
    {
    	struct Node
    	{
    		int l, r;
    	} SMT[N << 2];
    	int lazy[N << 2], val[N << 2];
    	
    	void pushup(int x)
    	{
    		val[x] = val[x << 1 | 1] + val[x << 1];
    	}
    	void pushdown(int x)
    	{
    		if(~lazy[x])
    		{
    			val[x << 1] = lazy[x] * (SMT[x << 1].r - SMT[x << 1].l + 1);
    			val[x << 1 | 1] = lazy[x] * (SMT[x << 1 | 1].r - SMT[x << 1 | 1].l + 1);
    			lazy[x << 1] = lazy[x];
    			lazy[x << 1 | 1] = lazy[x]; 
    			lazy[x] = -1;
    		}
    	}
    	
    	void prework()
    	{
    		memset(lazy, -1, sizeof lazy);
    		memset(val, 0, sizeof val);
    	}
    	
    	void build(int x, int l, int r, int k)
    	{
    		SMT[x].l = l, SMT[x].r = r;
    		if(l == r)
    		{
    			val[x] = a[l] >= k;
    			return ;
    		}
    		int mid = (l + r) >> 1;
    		build(x << 1, l, mid, k);
    		build(x << 1 | 1, mid + 1, r, k);
    		pushup(x);
    	}
    	void change(int p, int l, int r, int x, int y, int vall)
    	{
    		if (x <= l && r <= y)
    		{
    			val[p] = vall * (r - l + 1);
    			lazy[p] = vall;
    			return ;
    		}
    		if (l > y || r < x) return ;
    		pushdown(p);
    		int mid = (l + r) >> 1;
    		change(p << 1, l, mid, x, y, vall);
    		change(p << 1 | 1, mid + 1, r, x, y, vall);
    		pushup(p);
    	}
    	int query(int p , int l, int r, int x, int y)
    	{
    		if (x <= l && r <= y)
    		{
    			return val[p];
    		}
    		if (l > y || r < x) return 0;
    		pushdown(p);
    		int mid = (l + r) >> 1;
    		return query(p << 1, l, mid, x, y) + query(p << 1 | 1, mid + 1, r, x, y);
    	}
    }smt;
    
    int main()
    {
    	scanf("%d%d", &n, &m);
    	for (int i = 1; i <= n; i++)
    		scanf ("%d", &a[i]);
    	for (int i = 1; i <= m ; i++)
    		scanf ("%d%d%d", &input[i][0], &input[i][1], &input[i][2]);
    	scanf ("%d", &q);
    	int l = 1, r = n, ans, mid;
    	while(l <= r)
    	{
    		mid = (l + r) >> 1;
    		smt.prework();
    		smt.build(1, 1, n, mid);
    		for (int i = 1; i <= m; i++)
    		{
    			int cntOne = smt.query(1, 1, n, input[i][1], input[i][2]);
    			if (input[i][0])
    			{
    				smt.change(1, 1, n, input[i][1], input[i][1] + cntOne - 1, 1);
    				smt.change(1, 1, n, input[i][1] + cntOne, input[i][2], 0);
    			}else
    			{
    				smt.change(1, 1, n, input[i][2] - cntOne + 1, input[i][2], 1);
    				smt.change(1, 1, n, input[i][1], input[i][2] - cntOne, 0);
    			}
    		}
    		int k = smt.query(1, 1, n, q, q);
    		if(k) ans = mid, l = mid + 1;else r = mid - 1;
    	}
    	printf("%d
    ", ans);
    	return 0;
    }
    
    
  • 相关阅读:
    软工试水日报-纯js原生简易动态表格 3/15
    软工试水日报-Echarts动态柱形图 3/14
    大二下学期第一次结对作业(第一阶段)
    大二下学期之第一次结对作业(第一阶段)
    大二下每周总结
    大二下学期之第一次结对作业(第一阶段)
    大二下学期第一次结对作业(第一阶段)
    大二下学期第一次结对作业(第一阶段)
    大二下学期每日总结之第一次个人作业(第三阶段)
    大二下学期每日总结之第一次个人作业(第三阶段)
  • 原文地址:https://www.cnblogs.com/GJY-JURUO/p/13363521.html
Copyright © 2020-2023  润新知