给定长度为n的序列:a1,a2,…,an,记为a[1:n]。类似地,a[l:r](1≤l≤r≤N)是指序列:al,al+1,…,ar-
1,ar。若1≤l≤s≤t≤r≤n,则称a[s:t]是a[l:r]的子序列。现在有q个询问,每个询问给定两个数l和r,1≤l≤r
≤n,求a[l:r]的不同子序列的最小值之和。例如,给定序列5,2,4,1,3,询问给定的两个数为1和3,那么a[1:3]有
6个子序列a[1:1],a[2:2],a[3:3],a[1:2],a[2:3],a[1:3],这6个子序列的最小值之和为5+2+4+2+2+2=17。
1 #include<cstdio>
2 #include<iostream>
3 #include<cmath>
4 #include<cstring>
5 #include<algorithm>
6 using namespace std;
7 typedef long long int64;
8 char ch;
9 bool ok;
10 void read(int &x){
11 ok=0;
12 for (ch=getchar();!isdigit(ch);ch=getchar()) if (ch==‘-‘) ok=1;
13 for (x=0;isdigit(ch);x=x*10+ch-‘0‘,ch=getchar());
14 if (ok) x=-x;
15 }
16 const int inf=2147483647;
17 const int maxn=100005;
18 int n,q,a[maxn],x,y,l[maxn],r[maxn],top,stack[maxn];
19 struct segx{
20 int tot,root,son[16000000][4];
21 int64 sum[16000000],tag[16000000];
22 void init(){tot=root=1;}
23 void cover(int &k,int l1,int r1,int x1,int x2,int l2,int r2,int y1,int y2,int v){
24 if (!k) k=++tot;
25 if (x1<=l1&&r1<=x2&&y1<=l2&&r2<=y2){tag[k]+=v,sum[k]+=1LL*v*(r1-l1+1)*(r2-l2+1);return;}
26 int m1=(l1+r1)>>1,m2=(l2+r2)>>1;
27 if (x1<=m1&&y1<=m2) cover(son[k][0],l1,m1,x1,x2,l2,m2,y1,y2,v);
28 if (x1<=m1&&m2<y2) cover(son[k][2],l1,m1,x1,x2,m2+1,r2,y1,y2,v);
29 if (m1<x2&&y1<=m2) cover(son[k][1],m1+1,r1,x1,x2,l2,m2,y1,y2,v);
30 if (m1<x2&&m2<y2) cover(son[k][3],m1+1,r1,x1,x2,m2+1,r2,y1,y2,v);
31 sum[k]=0;
32 for (int i=0;i<4;i++) sum[k]+=sum[son[k][i]];
33 }
34 void cover(int x1,int x2,int y1,int y2,int v){cover(root,1,n,x1,x2,1,n,y1,y2,v);}
35 int64 query(int k,int l1,int r1,int x1,int x2,int l2,int r2,int y1,int y2,int64 t){
36 if (!k) return t*(min(r1,x2)-max(l1,x1)+1)*(min(r2,y2)-max(l2,y1)+1);
37 if (x1<=l1&&r1<=x2&&y1<=l2&&r2<=y2) return sum[k]+t*(r1-l1+1)*(r2-l2+1);
38 int m1=(l1+r1)>>1,m2=(l2+r2)>>1;
39 int64 res=0;
40 if (x1<=m1&&y1<=m2) res+=query(son[k][0],l1,m1,x1,x2,l2,m2,y1,y2,t+tag[k]);
41 if (x1<=m1&&m2<y2) res+=query(son[k][2],l1,m1,x1,x2,m2+1,r2,y1,y2,t+tag[k]);
42 if (m1<x2&&y1<=m2) res+=query(son[k][1],m1+1,r1,x1,x2,l2,m2,y1,y2,t+tag[k]);
43 if (m1<x2&&m2<y2) res+=query(son[k][3],m1+1,r1,x1,x2,m2+1,r2,y1,y2,t+tag[k]);
44 return res;
45 }
46 int64 query(int x1,int x2,int y1,int y2){return query(root,1,n,x1,x2,1,n,y1,y2,0);}
47 }Tx;
48 int main(){
49 read(n),read(q),Tx.init();
50 for (int i=1;i<=n;i++) read(a[i]);
51 a[0]=a[n+1]=-inf;
52 stack[top=1]=0;
53 for (int i=1;i<=n;i++){
54 while (top&&a[stack[top]]>=a[i]) top--;
55 l[i]=stack[top]+1;
56 stack[++top]=i;
57 }
58 stack[top=1]=n+1;
59 for (int i=n;i>=1;i--){
60 while (top&&a[stack[top]]>a[i]) top--;
61 r[i]=stack[top]-1;
62 stack[++top]=i;
63 }
64 for (int i=1;i<=n;i++) Tx.cover(l[i],i,i,r[i],a[i]);
65 while (q--) read(x),read(y),printf("%lld\n",Tx.query(x,y,x,y));
66 return 0;
67 }
第二种:
1 #include<cstdio>
2 #include<iostream>
3 #include<cmath>
4 #include<cstring>
5 #include<algorithm>
6 using namespace std;
7 typedef long long int64;
8 char ch;
9 bool ok;
10 void read(int &x){
11 for (ok=0,ch=getchar();!isdigit(ch);ch=getchar()) if (ch==‘-‘) ok=1;
12 for (x=0;isdigit(ch);x=x*10+ch-‘0‘,ch=getchar());
13 if (ok) x=-x;
14 }
15 const int maxn=100005;
16 const int inf=2147483647;
17 int n,q,a[maxn],stack[maxn],top;
18 int64 ans[maxn];
19 struct Quer{
20 int l,r,id;
21 void init(int i){read(l),read(r),id=i;}
22 }quer[maxn];
23 bool cmp(const Quer &a,const Quer &b){return a.r<b.r;}
24 struct Data{
25 int64 a,b,c,d;
26 void init(){a=1,b=c=d=0;}
27 };
28 Data operator+(const Data &x,const Data &y){return (Data){x.a*y.a,x.b*y.a+y.b,y.c*x.a+x.c,y.c*x.b+x.d+y.d};}
29 struct Seg{
30 #define ls k<<1
31 #define rs (k<<1)+1
32 int len[maxn<<2];
33 int64 v[maxn<<2],s[maxn<<2];
34 Data tag[maxn<<2];
35 void addtag(int k,Data t){s[k]=t.c*v[k]+t.d*len[k]+s[k],v[k]=t.a*v[k]+t.b*len[k],tag[k]=tag[k]+t;}
36 void pushdown(int k){addtag(ls,tag[k]),addtag(rs,tag[k]),tag[k].init();}
37 void update(int k){v[k]=v[ls]+v[rs],s[k]=s[ls]+s[rs];}
38 void build(int k,int l,int r){
39 tag[k].init(),len[k]=r-l+1;
40 if (l==r) return;
41 int m=(l+r)>>1;
42 build(ls,l,m),build(rs,m+1,r);
43 }
44 void cover(int k,int l,int r,int x,int y,Data t){
45 if (l==x&&r==y){addtag(k,t);return;}
46 int m=(l+r)>>1; pushdown(k);
47 if (y<=m) cover(ls,l,m,x,y,t);
48 else if (x<=m) cover(ls,l,m,x,m,t),cover(rs,m+1,r,m+1,y,t);
49 else cover(rs,m+1,r,x,y,t);
50 update(k);
51 }
52 void cover(int x,int y,int v){cover(1,1,n,x,y,(Data){0,v,0,0}),addtag(1,(Data){1,0,1,0});}
53 int64 query(int k,int l,int r,int x,int y){
54 if (l==x&&r==y) return s[k];
55 int m=(l+r)>>1; pushdown(k);
56 if (y<=m) return query(ls,l,m,x,y);
57 else if (x<=m) return query(ls,l,m,x,m)+query(rs,m+1,r,m+1,y);
58 else return query(rs,m+1,r,x,y);
59 }
60 int64 query(int x,int y){return query(1,1,n,x,y);}
61 }T;
62 int main(){
63 read(n),read(q),a[0]=-inf,T.build(1,1,n);
64 for (int i=1;i<=n;i++) read(a[i]);
65 for (int i=1;i<=q;i++) quer[i].init(i);
66 sort(quer+1,quer+q+1,cmp);
67 stack[top=1]=0;
68 for (int i=1,j=1;i<=n;i++){
69 while (top&&a[stack[top]]>=a[i]) top--;
70 T.cover(stack[top]+1,i,a[i]);
71 for (;quer[j].r==i;j++) ans[quer[j].id]=T.query(quer[j].l,quer[j].r);
72 stack[++top]=i;
73 }
74 for (int i=1;i<=q;i++) printf("%lld\n",ans[i]);
75 return 0;
76 }
第三种:
1 #include<cstdio>
2 #include<iostream>
3 #include<cmath>
4 #include<cstring>
5 #include<algorithm>
6 #include<cassert>
7 using namespace std;
8 typedef long long int64;
9 char ch;
10 bool ok;
11 void read(int &x){
12 ok=0;
13 for (ch=getchar();!isdigit(ch);ch=getchar()) if (ch==‘-‘) ok=1;
14 for (x=0;isdigit(ch);x=x*10+ch-‘0‘,ch=getchar());
15 if (ok) x=-x;
16 }
17 const int inf=2147483647;
18 const int maxn=100005;
19 const int maxm=maxn;
20 int n,q,a[maxn],x,y,l[maxn],r[maxn],top,stack[maxn],pos[maxn];
21 struct Graph{
22 int tot,now[maxn],son[maxm],pre[maxm];
23 int64 val[maxm],dis[maxn];
24 void put(int a,int b,int64 c){pre[++tot]=now[a],now[a]=tot,son[tot]=b,val[tot]=c;}
25 void dfs(int u){for (int p=now[u],v=son[p];p;p=pre[p],v=son[p]) dis[v]=dis[u]+val[p],dfs(v);}
26 }G[2];
27 int st[maxn][17],sn,bel[maxn];
28 int64 ans[maxn],res;
29 struct Queries{
30 int l,r,id;
31 void init(int i){read(l),read(r),id=i;}
32 }queries[maxn];
33 bool cmp(const Queries &a,const Queries &b){return bel[a.l]<bel[b.l]||(bel[a.l]==bel[b.l]&&bel[a.r]<bel[b.r]);}
34 int get_min(int i,int j){return a[i]<a[j]?i:j;}
35 int calc(int x,int y){
36 if (x>y) swap(x,y);
37 int step=pos[y-x+1];
38 return get_min(st[x][step],st[y-(1<<step)+1][step]);
39 }
40 void movel(int x,int y,int op){
41 int p=calc(x,y);
42 int64 tmp=G[1].dis[x]-G[1].dis[p]+1LL*a[p]*(y-p+1);
43 res+=op*tmp;
44 }
45 void mover(int x,int y,int op){
46 int p=calc(x,y);
47 int64 tmp=G[0].dis[y]-G[0].dis[p]+1LL*a[p]*(p-x+1);
48 res+=op*tmp;
49 }
50 void work(){
51 int l=1,r=1; res=a[1];
52 for (int i=1;i<=q;i++){
53 for (;r<queries[i].r;r++) mover(l,r+1,1);
54 for (;l>queries[i].l;l--) movel(l-1,r,1);
55 for (;r>queries[i].r;r--) mover(l,r,-1);
56 for (;l<queries[i].l;l++) movel(l,r,-1);
57 ans[queries[i].id]=res;
58 }
59 for (int i=1;i<=q;i++) printf("%lld\n",ans[i]);
60 }
61 int main(){
62 read(n),read(q),sn=sqrt(n),pos[0]=-1;
63 for (int i=1;i<=n;i++) bel[i]=i/sn;
64 for (int i=1;i<=n;i++) pos[i]=pos[i>>1]+1;
65 for (int i=1;i<=n;i++) read(a[i]);
66 for (int i=1;i<=n;i++) st[i][0]=i;
67 for (int j=1;j<=17;j++) for (int i=1;i<=n;i++){
68 st[i][j]=st[i][j-1];
69 if (i+(1<<(j-1))<=n) st[i][j]=get_min(st[i][j],st[i+(1<<(j-1))][j-1]);
70 }
71 a[0]=a[n+1]=-inf;
72 stack[top=1]=0;
73 for (int i=1;i<=n;i++){
74 while (top&&a[stack[top]]>=a[i]) top--;
75 G[0].put(stack[top],i,1LL*(i-stack[top])*a[i]);
76 stack[++top]=i;
77 }
78 stack[top=1]=n+1;
79 for (int i=n;i>=1;i--){
80 while (top&&a[stack[top]]>a[i]) top--;
81 G[1].put(stack[top],i,1LL*(stack[top]-i)*a[i]);
82 stack[++top]=i;
83 }
84 G[0].dfs(0),G[1].dfs(n+1);
85 for (int i=1;i<=q;i++) queries[i].init(i);
86 sort(queries+1,queries+q+1,cmp);
87 work();
88 return 0;
89 }