zoukankan      html  css  js  c++  java
  • P5358 [SDOI2019]快速查询

    P5358[SDOI2019]快速查询

    和当初对一轮D2T2有着同样的感觉吧,省选上最应该做出来的一道题(菜永远是原罪)
    首先对于(50\%)的数据,我们可以直接线段树过去
    但是,我们发现除了单点赋值和查询以外,其他的操作都是对全局进行的操作
    虽然元素有(10^9)个,但是,操作也最多只有(10^5)个,也就是说,修改或查询的位置,也最多是(10^5)个,只需要讲这(10^5)个位置,单独拿出来维护。
    而区间加法乘法和区间赋值我们都可以通过维护一个类似(kx+b)的形式
    其中(x)表示赋值,(k)表示乘,(b)表示加法
    优先级自然是(x > k > b),也就是说(k)会影响(b),(x)会影响(k)(b)
    之后在维护一个全局和就好了
    但是,还有一个问题
    就是单点修改后,(k,b)的值是不适用与我们新修改的值的.
    现在全局的(k,b),将某一个点修改为(v)
    只需要将这个点变成((v - b) /k)就可以了
    至于除法,由于答案是在模质数的意义下,直接逆元就好了
    线性求逆元或者费马小定理都是可以的
    博主是用类似(hash)表的方法维护修改的位置

    #include<cstdio>
    #include<iostream>
    #include<cctype>
    #include<cstring>
    #define LL long long
    using namespace std;
    const int N = 1e5 + 3;
    const LL mod = 1e7 + 19;
    struct Query{
    	int type;	
    	LL val;
    	int p;
    }q[N];
    LL ni[mod];
    inline LL read(){
    	LL v = 0,c = 1;char ch = getchar();
    	while(!isdigit(ch)){
    		if(ch == '-') c = -1;
    		ch = getchar();	
    	}
    	while(isdigit(ch)){
    		v = v * 10 + ch - 48;
    		ch = getchar();
    	}
    	return v * c;
    }
    struct edge{
    	int pos;
    	int nxt;	
    	int idx;
    	LL val;
    }e[N << 1];
    int head[mod + 2];
    int n,m,t,tot;
    inline void add(int x){
    	int st = q[x].p % mod;
    	 e[++tot].pos = q[x].p;
    	 e[tot].val = 0;
    	 e[tot].nxt = head[st];
    	 head[st] = tot;  
    }
    inline int getpos(int x){
    	int s = x % mod;
    	for(int i = head[s];i;i = e[i].nxt){
    		if(e[i].pos == x) return i;
    	}
    	return 0;
    }
    int main(){
    	ni[1] = 1;
    	for(int i = 2;i < mod;++i) ni[i] = mod - (mod / i) * ni[mod % i] % mod;
    	n = read(),m = read();
    	for(int i = 1;i <= m;++i){
    		q[i].type = read();
    		if(q[i].type == 1) q[i].p = read();
    		if(q[i].type != 6) q[i].val = 1ll * (read() % mod + mod) % mod;
    		if(q[i].type == 1) add(i);
    	}
    	LL mul = 1,add = 0,x = 0;
    	LL sum = 0,ans = 0;
    	LL last = 0;
    	int T = read();
    	for(int j = 1;j <= T;++j){
    		LL xx = read(),yy = read();
    	//	cout << x << " " << y << endl;
    		for(int i = 1;i <= m;++i){
    			
    			int w = (xx + 1ll * i * yy) % m + 1;
    		//	if(q[w].type >= 5)
    		//	printf("%d %d %d %lld
    ",w,q[w].type,q[w].p,q[w].val);
    			if(q[w].type == 1){
    				int s = getpos(q[w].p);
    				if(last && e[s].idx < last)
    					sum = ((sum - x * mul - add) % mod + mod) % mod;	
    				else sum = ((sum - e[s].val * mul - add) % mod + mod) % mod;
    				e[s].idx = j * m + i;
    				e[s].val = ((q[w].val - add) * ni[mul]) % mod + mod;
    				e[s].val %= mod;
    				sum = (sum + q[w].val) % mod; 
    			}	
    			if(q[w].type == 2){
    				sum = (sum + 1ll * n * q[w].val) % mod;
    				add = (add + q[w].val) % mod;	
    			}
    			if(q[w].type == 3 && q[w].val == 0) q[w].type = 4;
    			if(q[w].type == 3){
    				sum = (sum * q[w].val) % mod;
    				mul = mul * q[w].val % mod;	
    				add = (add * q[w].val) % mod;
    			}
    			if(q[w].type == 4){
    				mul = 1,add = 0;
    				sum = 1ll * n * q[w].val % mod;
    				last = j * m + i;
    				x = q[w].val;
    			}
    			if(q[w].type == 5){
    				int s = getpos(q[w].val);
    				if(s == 0) ans = (ans + x * mul + add) % mod;
    				else if(last && e[s].idx < last) ans = (ans + x * mul + add) % mod;
    				else ans = (ans + e[s].val * mul + add) % mod;  	
    			}
    			if(q[w].type == 6) ans = (ans + sum) % mod;
    		//	cout << ans << endl;
    		}
    	}
    	printf("%lld
    ",ans);
    	return 0;	
    }
    
  • 相关阅读:
    关于JsonObject的笔记
    addHeader() 与 setHeader() 区别
    BeanUtils.copyProperties(A,B)字段复制用法
    servletcontext的小结
    枚举笔记
    关于spring mvc接受前台参数的笔记
    关于session和cookie
    servlet学习
    tomcat到底是干嘛的
    .json文件报错 ,点进去是Expected value at 1:0
  • 原文地址:https://www.cnblogs.com/wyxdrqc/p/10830999.html
Copyright © 2011-2022 走看看