• vijos2051 SDOI2019 快速查询


    题目链接

    吐槽

    竟然让(nlog)的做法卡过去了。。

    思路

    因为(1 le q le 10^5),所以可以先对每个标准操作,所操作的位置进行重标号。这样所有的下标都是在(10^5)以内的。

    乘和加操作都可以写成(kx+b)的形式。然后对于这些操作维护一个前缀。然后就可以得到一个区间内的操作了。

    区间查询我们只要找个(TOT)来维护一下当前的所有元素和,就行了。

    单点查询,观察其上次赋值的时间。如果早于集体赋值,那么就输出当前大多数的值。

    否则就将其上次赋的值乘上从上次赋值到当前时间点这个时间段内的操作。

    代码

    /*
    * @Author: wxyww
    * @Date:   2019-05-07 20:58:04
    * @Last Modified time: 2019-05-11 10:33:03
    */
    #include<cstdio>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<vector>
    #include<ctime>
    #include<map>
    using namespace std;
    typedef long long ll;
    const int N = 100010,mod = 1e7 + 19;
    map<int,int>ma;
    ll read() {
    	ll x=0,f=1;char c=getchar();
    	while(c<'0'||c>'9') {
    		if(c=='-') f=-1;
    		c=getchar();
    	}
    	while(c>='0'&&c<='9') {
    		x=x*10+c-'0';
    		c=getchar();
    	}
    	return x*f;
    }
    struct node {
    	int opt,pos,val;
    }que[N];
    int TOT,s[N],a[N],b[N],now,inv[mod + 1],n,T,Q,mul[N * 100],add[N * 100];
    int lst[N],LAST;
    int query(int x,int num) {
    	if(lst[x] <= LAST) return now;
    	int cheng = 1ll * mul[num] * inv[mul[lst[x]]] % mod;
    	int jia = (add[num] - 1ll * add[lst[x] - 1] * cheng % mod + mod) % mod;
    	return (1ll * s[x] * cheng % mod + jia) % mod;
    }
    int ans;
    void solve(int x,int num) {
    	int opt = que[x].opt,pos = que[x].pos,val = que[x].val % mod;
    	mul[num] = mul[num - 1],add[num] = add[num - 1];
    	if(opt == 1) {
    		TOT -= query(pos,num);
    		TOT += val;
    		TOT = (TOT % mod + mod) % mod;
    		lst[pos] = num;
    		s[pos] = val;
    	}
    	else if(opt == 2) {
    		TOT += (1ll * n * val % mod + mod) % mod;
    		TOT = (TOT % mod + mod) % mod;
    		add[num] += val;
    		add[num] = (add[num] %mod + mod) % mod;
    		now += val;
    		now = (now % mod + mod) % mod;
    	}
    	else if(opt == 3) {
    		TOT = (1ll * TOT * val % mod + mod) % mod;
    		now = (1ll * now * val % mod + mod) % mod;
    		add[num] = (1ll * add[num] * val % mod + mod) % mod;
    		mul[num] = (1ll * mul[num] * val % mod + mod) % mod;
    	}
    	else if(opt == 4) { 
    		TOT = (1ll * val * n % mod + mod) % mod;
    		mul[num] = 1;add[num] = 0;
    		now = val;
    		LAST = num;
    	}
    	else if(opt == 5) ans += query(pos,num),ans = (ans % mod + mod) % mod;
    	else ans = ((ans + TOT) % mod + mod) % mod;
    }
    int main() {
    	n = read(),Q = read();
    	for(int i = 1;i <= Q;++i) {
    		int opt = que[i].opt = read();
    		if(opt == 1) {
    			que[i].pos = read();que[i].val = read();
    		}
    		else if(opt == 6) continue;
    		else if(opt == 5) que[i].pos = read();
    		else que[i].val = read();
    	}
    
    	inv[1] = 1;
    	for(int i =  2;i < mod;++i) inv[i] = 1ll * (mod - mod / i) * inv[mod % i] % mod;
    
    	int js = 0;
    	for(int i = 1;i <= Q;++i) {
    		if(!que[i].pos) continue;
    		if(!ma[que[i].pos]) 	ma[que[i].pos] = ++js;
    		que[i].pos = ma[que[i].pos];
    	}
    
    	int T = read(),num = 0;
    	for(int i = 1;i <= T;++i) a[i] = read(),b[i] = read();
    	for(int i = 1;i <= T;++i)
    		for(int j = 1;j <= Q;++j)
    			solve((a[i] + 1ll * j * b[i] % Q) % Q + 1,++num);
    
    	cout<<(ans % mod + mod) % mod;
    	return 0;
    }
    
  • 相关阅读:
    Java-LockSupport
    Kafka Eagle 安装
    Kafka shell
    python pip 使用
    Kafka 集群部署
    Kafka 概述
    DockerFile 简单使用
    《深入理解Java虚拟机》读书笔记
    linux安装redis
    Java多线程基础知识例子
  • 原文地址:https://www.cnblogs.com/wxyww/p/vijos2051.html
Copyright © 2020-2023  润新知