题解:我们考虑到不包含重复元素 那么我们对每一个位置上的点都维护一个这个点的前驱节点 那么对于每个节点来说 都拥有两个关键字 问题转化为查询[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 ",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 ",ans);} } }
2883: gss2加强版
Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 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
1 2 4 2 3
3
Q 2 4
U 4 7
Q 2 4
Sample Output
6
13
13
HINT
2017.4.27新加数据一组 By nzhtl1477,时限放到20s,并重测