zoukankan      html  css  js  c++  java
  • 题解 「清华集训2014」玄学

    题目传送门

    题目大意

    给出一个 (n) 个点的序列,有 (m) 次操作,每次操作为以下两种:

    • (l o r) 的点都变为 (ax+b)

    • 查询在 (l o r) 修改操作情况下序列第 (k) 个数是多少。

    强制在线,(nle 10^5,mle 6 imes 10^5)

    思路

    二进制分组好啊!!!

    跟普通的二进制分组不太一样,这道题查询的一段区间的操作总和,所以我们自然而言地想到了线段树,而且线段树有一个好处,就是说每一段恰好就是 (2^x) 这种形态的,于是查询的时候直接跟在线段树查询一样地操作即可。

    考虑修改操作,我们发现其实每次修改,都会有一段一段的区间是相同的变化规则,我们可以根据这个将两个操作进行合并。

    考虑时间复杂度,你每次增加的时候最多增加 (3) 段,于是总段数就是 (nlog^2 n),总时间复杂度也是 (Theta(nlog^2 n))(假设 (n,m) 同阶)

    ( exttt{Code})

    #include <bits/stdc++.h>
    using namespace std;
    
    #define Int register int
    #define MAXM 600005
    #define MAXN 100005
    
    template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
    template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);}
    template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');}
    
    int n,m,k,q,cnt,ans,kase,val[MAXN],lef[MAXM << 2],rig[MAXM << 2];
    
    struct node{
    	int l,r,a,b;//表示l->r这段区间都变为ax+b
    	node(){}
    	node (int _l,int _r,int _a,int _b){l = _l,r = _r,a = _a,b = _b;} 
    }p[MAXM * 200];
    
    void Pushup (int x){
    	lef[x] = cnt + 1;
    	for (Int i = lef[x << 1],j = lef[x << 1 | 1],las = 1;i <= rig[x << 1] || j <= rig[x << 1 | 1];)
    		if (p[i].r <= p[j].r){
    			p[++ cnt] = node (las,p[i].r,1ll * p[i].a * p[j].a % m,(1ll * p[i].b * p[j].a % m + p[j].b) % m);
    			las = p[i].r + 1;
    			if (p[i].r == p[j].r) ++ i,++ j;
    			else ++ i; 
    		}
    		else{
    			p[++ cnt] = node (las,p[j].r,1ll * p[i].a * p[j].a % m,(1ll * p[i].b * p[j].a % m + p[j].b) % m);
    			las = p[j].r + 1,++ j;
    		}
    	rig[x] = cnt;
    }
    
    void find (int x,int t,int &s){//在x维护的段内 
    	int l = lef[x],r = rig[x];
    	while (l < r){
    		int mid = (l + r) >> 1;
    		if (t <= p[mid].r) r = mid;
    		else l = mid + 1;
    	}
    	s = (1ll * s * p[l].a % m + p[l].b) % m;
    }
    
    void Modify (int x,int l,int r,int pos,node &t){
    	if (l == r){
    		lef[x] = cnt + 1;
    		if (t.l > 1) p[++ cnt] = node (1,t.l - 1,1,0);
    		p[++ cnt] = t;
    		if (t.r < n) p[++ cnt] = node (t.r + 1,n,1,0);
    		rig[x] = cnt;
    		return ;
    	}
    	int mid = (l + r) >> 1;
    	if (pos <= mid) Modify (x << 1,l,mid,pos,t);
    	else Modify (x << 1 | 1,mid + 1,r,pos,t);
    	if (pos == r) Pushup (x);
    }
    
    void Query (int x,int l,int r,int ql,int qr){
    	if (ql <= l && r <= qr) return find (x,k,ans);
    	int mid = (l + r) >> 1;
    	if (ql <= mid) Query (x << 1,l,mid,ql,qr);
    	if (qr > mid) Query (x << 1 | 1,mid + 1,r,ql,qr);
    }
    
    signed main(){
    	read (kase,n,m);
    	for (Int i = 1;i <= n;++ i) read (val[i]);
    	read (q);int tot = 0;
    	for (Int i = 1;i <= q;++ i){
    		int opt,l,r;read (opt,l,r);
    		if (kase & 1) l ^= ans,r ^= ans;
    		if (opt == 1){
    			int ta,tb;read (ta,tb);
    			node now = node (l,r,ta,tb);
    			Modify (1,1,q,++ tot,now);
    		}
    		else{
    			read (k);
    			if (kase & 1) k ^= ans;
    			ans = val[k],Query (1,1,q,l,r);
    			write (ans),putchar ('
    ');
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    luogu 2491 [SDOI2011]消防 / 1099 树网的核 单调队列 + 树上问题
    BZOJ 1179: [Apio2009]Atm tarjan + spfa
    BZOJ 1112: [POI2008]砖块Klo Splay + 性质分析
    BZOJ 1596: [Usaco2008 Jan]电话网络 树形DP
    BZOJ 2060: [Usaco2010 Nov]Visiting Cows 拜访奶牛 树形DP
    CF286E Ladies' Shop FFT
    CF528D Fuzzy Search FFT
    BZOJ 3771: Triple 生成函数 + FFT
    BZOJ 3513: [MUTC2013]idiots FFT
    python爬虫网页解析之parsel模块
  • 原文地址:https://www.cnblogs.com/Dark-Romance/p/13642499.html
Copyright © 2011-2022 走看看