BZOJ2883: gss2加强版

题解:我们考虑到不包含重复元素 那么我们对每一个位置上的点都维护一个这个点的前驱节点 那么对于每个节点来说  都拥有两个关键字 问题转化为查询[l,r]前驱节点的值小于l的数的和 那我们可以用线段树套线段树解决此题

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#include <queue>
#include <cmath>
#include <set>
#include <map>
#define mp make_pair
#define pb push_back
#define pii pair<int,int>
#define link(x) for(edge *j=h[x];j;j=j->next)
#define inc(i,l,r) for(int i=l;i<=r;i++)
#define dec(i,r,l) for(int i=r;i>=l;i--)
const int MAXN=1e5+10;
const double eps=1e-8;
#define ll long long
using namespace std;
struct edge{int t;edge*next;}e[MAXN<<1],*h[MAXN],*o=e;
void add(int x,int y){o->t=y;o->next=h[x];h[x]=o++;}
ll read(){
	ll x=0,f=1;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
	while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
	return x*f;
}
typedef struct node{
	int id,vul;
	friend bool operator<(node aa,node bb){
		if(aa.vul==bb.vul)return aa.id<bb.id;
		return aa.vul<bb.vul;
	}
}node;
set<node>s;
set<node>::iterator ite,ip;
int d[MAXN<<2],cnt,n,m;
void debug(){
	for(ite=s.begin();ite!=s.end();ite++)cout<<(*ite).id<<" "<<(*ite).vul<<endl;
}
typedef struct Node{
	int l,r;ll sum;
}Node;
Node p[MAXN*61];
int key,id,a[MAXN];
void update1(int &x,int l,int r){
	if(!x)x=++cnt;
	p[x].sum+=key;
	if(l==r)return ;
	int mid=(l+r)>>1;
	if(id<=mid)update1(p[x].l,l,mid);
	else update1(p[x].r,mid+1,r);
}
void update(int rt,int l,int r,int t){
	update1(d[rt],1,n);
	if(l==r)return ;
	int mid=(l+r)>>1;
	if(t<=mid)update(rt<<1,l,mid,t);
	else update(rt<<1|1,mid+1,r,t);
}
ll ans,ans1;
void querty1(int x,int l,int r){
	if(1<=l&&r<=id){ans1+=p[x].sum;return ;}
	int mid=(l+r)>>1;
	if(1<=mid)querty1(p[x].l,l,mid);
	if(id>mid)querty1(p[x].r,mid+1,r);
}
void querty(int rt,int l,int r,int ql,int qr){
	if(ql<=l&&r<=qr){ans1=0;querty1(d[rt],1,n);ans+=ans1;return ;}
	int mid=(l+r)>>1;
	if(ql<=mid)querty(rt<<1,l,mid,ql,qr);
	if(qr>mid)querty(rt<<1|1,mid+1,r,ql,qr);
}
int main(){
	n=read();
	inc(i,1,n){
		a[i]=read();
		ite=s.upper_bound((node){i,a[i]});
		if(ite==s.begin())id=1,key=a[i],update(1,1,n,i);
		else {
			ite--;
			if((*ite).vul!=a[i])id=1,key=a[i],update(1,1,n,i);
			else id=(*ite).id+1,key=a[i],update(1,1,n,i);
		}
		s.insert((node){i,a[i]});
		//cout<<i<<" "<<id<<" "<<a[i]<<endl;
	}
	m=read();char ch;int x,y;
	while(m--){
		scanf(" %c",&ch);x=read();y=read();
		if(ch=='U'){
			int pre,pre1;
			ite=s.lower_bound((node){x,a[x]});ip=ite;
			if(ite!=s.begin()){
				ite--;
				if((*ite).vul==a[x])id=(*ite).id+1;
				else id=1;
				ite++;
			}
			else id=1;
			pre=id;
			key=-a[x];update(1,1,n,x);
			if(ite!=s.end()){
				ite++;
				if((*ite).vul==a[x]){
					id=x+1;key=-a[x];update(1,1,n,(*ite).id);
					id=pre;key=a[x];update(1,1,n,(*ite).id);
				}#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#include <queue>
#include <cmath>
#include <set>
#include <map>
#define mp make_pair
#define pb push_back
#define pii pair<int,int>
#define link(x) for(edge *j=h[x];j;j=j->next)
#define inc(i,l,r) for(int i=l;i<=r;i++)
#define dec(i,r,l) for(int i=r;i>=l;i--)
const int MAXN=1e5+10;
const double eps=1e-8;
#define ll long long
using namespace std;
struct edge{int t;edge*next;}e[MAXN<<1],*h[MAXN],*o=e;
void add(int x,int y){o->t=y;o->next=h[x];h[x]=o++;}
ll read(){
	ll x=0,f=1;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
	while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
	return x*f;
}
typedef struct node{
	int id,vul;
	friend bool operator<(node aa,node bb){
		if(aa.vul==bb.vul)return aa.id<bb.id;
		return aa.vul<bb.vul;
	}
}node;
set<node>s;
set<node>::iterator ite,ip;
int d[MAXN<<2],cnt,n,m;
void debug(){
	for(ite=s.begin();ite!=s.end();ite++)cout<<(*ite).id<<" "<<(*ite).vul<<endl;
}
typedef struct Node{
	int l,r;ll sum;
}Node;
Node p[MAXN*61];
int key,id,a[MAXN];
void update1(int &x,int l,int r){
	if(!x)x=++cnt;
	p[x].sum+=key;
	if(l==r)return ;
	int mid=(l+r)>>1;
	if(id<=mid)update1(p[x].l,l,mid);
	else update1(p[x].r,mid+1,r);
}
void update(int rt,int l,int r,int t){
	update1(d[rt],1,n);
	if(l==r)return ;
	int mid=(l+r)>>1;
	if(t<=mid)update(rt<<1,l,mid,t);
	else update(rt<<1|1,mid+1,r,t);
}
ll ans,ans1;
void querty1(int x,int l,int r){
	if(1<=l&&r<=id){ans1+=p[x].sum;return ;}
	int mid=(l+r)>>1;
	if(1<=mid)querty1(p[x].l,l,mid);
	if(id>mid)querty1(p[x].r,mid+1,r);
}
void querty(int rt,int l,int r,int ql,int qr){
	if(ql<=l&&r<=qr){ans1=0;querty1(d[rt],1,n);ans+=ans1;return ;}
	int mid=(l+r)>>1;
	if(ql<=mid)querty(rt<<1,l,mid,ql,qr);
	if(qr>mid)querty(rt<<1|1,mid+1,r,ql,qr);
}
int main(){
	n=read();
	inc(i,1,n){
		a[i]=read();
		ite=s.upper_bound((node){i,a[i]});
		if(ite==s.begin())id=1,key=a[i],update(1,1,n,i);
		else {
			ite--;
			if((*ite).vul!=a[i])id=1,key=a[i],update(1,1,n,i);
			else id=(*ite).id+1,key=a[i],update(1,1,n,i);
		}
		s.insert((node){i,a[i]});
		//cout<<i<<" "<<id<<" "<<a[i]<<endl;
	}
	m=read();char ch;int x,y;
	while(m--){
		scanf(" %c",&ch);x=read();y=read();
		if(ch=='U'){
			int pre,pre1;
			ite=s.lower_bound((node){x,a[x]});ip=ite;
			if(ite!=s.begin()){
				ite--;
				if((*ite).vul==a[x])id=(*ite).id+1;
				else id=1;
				ite++;
			}
			else id=1;
			pre=id;
			key=-a[x];update(1,1,n,x);
			if(ite!=s.end()){
				ite++;
				if((*ite).vul==a[x]){
					id=x+1;key=-a[x];update(1,1,n,(*ite).id);
					id=pre;key=a[x];update(1,1,n,(*ite).id);
				}
			}
			s.erase(ip);
			ite=s.lower_bound((node){x,y});
			pre=pre1=0;
			if(ite!=s.end()&&(*ite).vul==y){
				pre1=(*ite).id;
			}
			if(ite==s.begin())pre=1;
			else{
				ite--;
				if((*ite).vul==y)pre=(*ite).id+1;
				else pre=1;
			}
			if(pre1)key=-y,id=pre,update(1,1,n,pre1),key=y,id=x+1,update(1,1,n,pre1);
			key=y;id=pre;update(1,1,n,x);
			a[x]=y;s.insert((node){x,y});
		}
		else{ans=0;id=x;querty(1,1,n,x,y);printf("%lld\n",ans);}
	}
}
			}
			s.erase(ip);
			ite=s.lower_bound((node){x,y});
			pre=pre1=0;
			if(ite!=s.end()&&(*ite).vul==y){
				pre1=(*ite).id;
			}
			if(ite==s.begin())pre=1;
			else{
				ite--;
				if((*ite).vul==y)pre=(*ite).id+1;
				else pre=1;
			}
			if(pre1)key=-y,id=pre,update(1,1,n,pre1),key=y,id=x+1,update(1,1,n,pre1);
			key=y;id=pre;update(1,1,n,x);
			a[x]=y;s.insert((node){x,y});
		}
		else{ans=0;id=x;querty(1,1,n,x,y);printf("%lld\n",ans);}
	}
}

  

2883: gss2加强版

Time Limit: 20 Sec  Memory Limit: 128 MB
Submit: 255  Solved: 66
[Submit][Status][Discuss]

Description

给你N个数,你需要支持一下两种操作。
U x y,讲第x个数修改成y;
Q x y,计算从第x个数至第y个数中不同数的和并输出。如对于一段数{1,2,3,2,7},它的值是13(1+2+3+7)。

Input

第一行N表示数的个数(1<=N<=100000);
第二行包含这N个数;
第三行M表示操作次数(1<=N<=100000);
接下来M行每行三个数表示题目描述的操作。
所有的输入均在int以内。
N<=100000,M<=100000

Output

对于每个Q操作返回一个值。

Sample Input

5
1 2 4 2 3
3
Q 2 4
U 4 7
Q 2 4

Sample Output

6
13

HINT

 

2017.4.27新加数据一组  By nzhtl1477,时限放到20s,并重测

posted @ 2018-09-20 15:53  wang9897  阅读(230)  评论(0编辑  收藏  举报