其实多一个(或者两个) lg(n) 的代码还是挺快的……
本题比较快的一个实现是主席树 , 第一次写 , 模版时间并不理想 , 优化时间这玩意就当作留一个坑以后填罢
主席树版代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <string>
#include <vector>
#include <deque>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <algorithm>
#include <cassert>
using namespace std;
const int maxn = 1e5+1e2;
const int INF = 0x3f3f3f3f;
typedef long long ll;
int n , m;
int s[maxn] , e[maxn] , p[maxn];
__inline int re() {
int n = 0, ch = getchar(); bool flag = false;
while(!isdigit(ch)) flag |= ch == '-', ch = getchar();
while(isdigit(ch)) n = n * 10 + ch - '0', ch = getchar();
return flag ? -n : n;
}
vector<int> as;
void concrete()
{
for(int i=1;i<=n;i++) as.push_back(p[i]);
sort(as.begin() , as.end());
as.erase(unique(as.begin() , as.end()) , as.end());
for(int i=1;i<=n;i++) p[i] = lower_bound(as.begin() , as.end() , p[i]) - as.begin();
}
struct node
{
node* ch[2];
ll num , s;
node(){ s = num = 0; }
void maintain() { s = ch[0]->s + ch[1]->s; num = ch[0]->num + ch[1]->num; }
};
node pool[maxn*100]; int CNT;
node* null = new node();
node* root[maxn];
node* newNode()
{
pool[CNT].ch[0] = pool[CNT].ch[1] = null;
return &pool[CNT++];
}
node* modify(node* o , int l , int r , int p , int a)
{
node* res = newNode();
*res = *o;
if(l == r)
{
res->num += a;
res->s += (ll)a*as[l];
//cout<<as[l]<<endl;
return res;
}
int mid = (l+r)/2;
if(p <= mid) res->ch[0] = modify(o->ch[0] , l , mid , p , a);
else res->ch[1] = modify(o->ch[1] , mid+1 , r , p , a);
res->maintain();
return res;
}
ll query(node* o , int l , int r , int k)
{
if(o->num <= k) return o->s;
if(l==r) return (ll)as[l] * k;
int mid = (l+r)/2;
if(o->ch[0]->num >= k) return query(o->ch[0] , l , mid , k);
else return o->ch[0]->s + query(o->ch[1] , mid+1 , r , k-o->ch[0]->num);
}
struct state
{
int a , b , c;
state(int a=0 , int b=0 , int c=0):a(a),b(b),c(c){}
bool operator <(const state& d)const { return a < d.a; }
};
vector<state> ts;
int main()
{
null->ch[0] = null->ch[1] = null;
cin>>n>>m;
for(int i=1;i<=n;i++) s[i] = re() , e[i] = re() , p[i] = re();
concrete();
for(int i=1;i<=n;i++) ts.push_back(state(s[i] , p[i] , 1)) , ts.push_back(state(e[i]+1 , p[i] , -1));
sort(ts.begin() , ts.end());
int len = as.size();
root[0] = null;
for(int i=1 , j=0;i<=n;i++)
{
node* now = root[i-1];
while(j<ts.size() && ts[j].a == i)
{
now = modify(now , 0 , len-1 , ts[j].b , ts[j].c);
j++;
}
root[i] = now;
}
ll pre = 1 , x , a , b , c , k;
while(m--)
{
x = re(); a = re(); b = re(); c = re();
k = 1 + (a*pre + b)%c;
printf("%lld\n" , pre = query(root[x] , 0 , len-1 , k));
}
return 0;
}
暴力版代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <string>
#include <vector>
#include <deque>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <algorithm>
#include <cassert>
using namespace std;
typedef long long ll;
const int maxn = 1e5+1e2;
int n , m;
vector<ll> a[maxn*10];
vector<ll> s[maxn*10];
void add(int o , int l , int r , int L , int R , ll added)
{
if(L <= l && r <= R)
{
a[o].push_back(added);
return;
}
int mid = (l+r)/2;
if(L <= mid) add(o*2 , l , mid , L , R , added);
if(R > mid) add(o*2+1 , mid+1 , r , L , R , added);
}
void build(int o , int l , int r)
{
sort(a[o].begin() , a[o].end());
s[o].resize(a[o].size());
for(int i=0;i<a[o].size();i++) s[o][i] = (i==0?0:s[o][i-1]) + a[o][i];
if(l==r) return;
else
{
int mid = (l+r)/2;
build(o*2 , l , mid);
build(o*2+1 , mid+1 , r);
}
}
int KKK;
int query(int o , int l , int r , int x , int mx , ll& sum)
{
int res = upper_bound(a[o].begin() , a[o].end() , mx) - a[o].begin();
if(res) sum += s[o][res-1];
if(l==r) return res;
if(res > KKK) return res;
int mid =(l+r)/2;
if(x<=mid) res += query(o*2 , l , mid , x , mx , sum);
else res += query(o*2+1 , mid+1 , r , x , mx , sum);
return res;
}
int Max;
ll query(int x , int k)
{
int l = 0 , r = Max;
ll res;
KKK = k;
while(l+1<r)
{
int mid = (l+r)/2;
if(query(1 , 1 , n , x , mid , res = 0) < k) l = mid;
else r = mid;
}
ll now = query(1 , 1 , n , x , r , res = 0);
return res - max(now-k , 0LL)*r;
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
int a , b , c;
scanf("%d%d%d" , &a , &b , &c);
add(1 , 1 , n , a , b , (ll)c);
Max = max(c , Max);
}
build(1 , 1 , n);
ll pre = 1;
while(m--)
{
ll x , a , b , c , k;
scanf("%lld%lld%lld%lld" , &x , &a , &b , &c);
k = 1 + (a*pre+b)%c;
printf("%lld\n" , pre = query(x , k));
}
return 0;
}