[单调栈专题]
https://vjudge.net/contest/296911#overview
A - Subsequence
Input
There are multiple test cases.
For each test case, the first line has three integers, n, m and k. n is the length of the sequence and is in the range [1, 100000]. m and k are in the range [0, 1000000]. The second line has n integers, which are all in the range [0, 1000000].
Proceed to the end of file.
Output
For each test case, print the length of the subsequence on a single line.
Sample Input
5 0 0 1 1 1 1 1 5 0 3 1 2 3 4 5
Sample Output
5 4
题意:求满足区间内最大元素值-最小元素值>=m&&<=k的最长区间长度
题解:两个单调栈,一个栈维护一个递增序列,另一个栈维护一个递减序列,通过二者差值<=k移动head指针,然后检查是否>=m更新ans
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<queue> 5 #include<set> 6 #include<map> 7 #include<stack> 8 #include<vector> 9 #include<cmath> 10 #include<algorithm> 11 using namespace std; 12 typedef long long ll; 13 #define debug(x,y,z) cout<< #x <<" is "<<x<<" "<< #y <<" is "<<y<<" "<< #z <<" is "<<z<<endl; 14 #define debugs(x) cout<< #x <<" is "<<x<<endl; 15 const ll inf=1e10; 16 ll a[100005]; 17 int q[100005],w[100005]; 18 int main() 19 { 20 int n,m,k; 21 while(scanf("%d",&n)==1){ 22 scanf("%d%d",&m,&k); 23 for(int i=1;i<=n;i++){ 24 scanf("%lld",&a[i]); 25 } 26 int ans=0; 27 int head,tail,head2,tail2; 28 head=1; 29 tail=0; 30 head2=1; 31 tail2=0; 32 int pre=1; 33 for(int i=1;i<=n;i++){ 34 while(tail>=head&&a[q[tail]]>a[i])tail--; 35 while(tail2>=head2&&a[w[tail2]]<a[i])tail2--; 36 q[++tail]=i; 37 w[++tail2]=i; 38 while(head<=tail&&head2<=tail2&&a[w[head2]]-a[q[head]]>k){ 39 if(q[head]<w[head2]){ 40 pre=q[head++]+1; 41 } 42 else{ 43 pre=w[head2++]+1; 44 } 45 } 46 if(a[w[head2]]-a[q[head]]<=k&&a[w[head2]]-a[q[head]]>=m){ 47 ans=max(ans,i-pre+1); 48 } 49 // debugs(w[head2]); 50 // debugs(q[head]); 51 } 52 printf("%d\n",ans); 53 } 54 return 0; 55 }
B - Second My Problem First
Then we define S i = A i mod B and T i = Min{ S k | i-A <= k <= i, k >= 1}
Your task is to calculate the product of T i (1 <= i <= n) mod B.
Input
Each line will contain three integers n(1 <= n <= 10 7),A and B(1 <= A, B <= 2 31-1).
Process to end of file.
Output
For each case, output the answer in a single line.
Sample Input
1 2 3 2 3 4 3 4 5 4 5 6 5 6 7
Sample Output
2 3 4 5 6
题意: S i = A i mod B ,T i = Min{ S k | i-A <= k <= i, k >= 1} ,求Ti(1<=i<=n)乘积%B的结果
题解:水题。直接维护一个单调栈即可线性求出所有Ti
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<queue> 5 #include<set> 6 #include<map> 7 #include<stack> 8 #include<vector> 9 #include<cmath> 10 #include<algorithm> 11 using namespace std; 12 typedef long long ll; 13 #define debug(x,y,z) cout<< #x <<" is "<<x<<" "<< #y <<" is "<<y<<" "<< #z <<" is "<<z<<endl; 14 #define debugs(x) cout<< #x <<" is "<<x<<endl; 15 int a[10000005],b[10000005]; 16 int main() 17 { 18 ll n,A,B; 19 while(scanf("%lld%lld%lld",&n,&A,&B)==3){ 20 a[0]=1; 21 for(int i=1;i<=n;i++)a[i]=a[i-1]*A%B; 22 int head=1; 23 int tail=0; 24 ll ans=1; 25 for(int i=1;i<=n;i++){ 26 while(head<=tail&&a[b[tail]]>=a[i])tail--; 27 b[++tail]=i; 28 while(head<=tail&&(b[head])<(i-A))head++; 29 ans=ans*a[b[head]]%B; 30 } 31 printf("%lld\n",ans); 32 } 33 return 0; 34 }
D - Largest Rectangle in a Histogram
Usually, histograms are used to represent discrete distributions, e.g., the frequencies of characters in texts. Note that the order of the rectangles, i.e., their heights, is important. Calculate the area of the largest rectangle in a histogram that is aligned at the common base line, too. The figure on the right shows the largest aligned rectangle for the depicted histogram.
Input
Output
Sample Input
7 2 1 4 5 1 3 3 4 1000 1000 1000 1000 0
Sample Output
8 4000
Hint
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<queue> 5 #include<set> 6 #include<map> 7 #include<stack> 8 #include<vector> 9 #include<cmath> 10 #include<algorithm> 11 using namespace std; 12 typedef long long ll; 13 #define debug(x,y,z) cout<< #x <<" is "<<x<<" "<< #y <<" is "<<y<<" "<< #z <<" is "<<z<<endl; 14 #define debugs(x) cout<< #x <<" is "<<x<<endl; 15 ll a[100005],b[100005],c[100005],d[100005]; 16 int main() 17 { 18 int n; 19 while(scanf("%d",&n)&&n){ 20 for(int i=1;i<=n;i++)scanf("%lld",&a[i]); 21 int tot=0; 22 b[0]=0; 23 for(int i=1;i<=n;i++){ 24 while(tot&&a[b[tot]]>=a[i])tot--; 25 c[i]=b[tot]+1; 26 b[++tot]=i; 27 } 28 b[0]=n+1; 29 tot=0; 30 for(int i=n;i>=1;i--){ 31 while(tot&&a[b[tot]]>=a[i])tot--; 32 d[i]=b[tot]-1; 33 b[++tot]=i; 34 } 35 ll ans=0; 36 for(int i=1;i<=n;i++){ 37 ans=max(ans,(d[i]-c[i]+1)*a[i]); 38 } 39 printf("%lld\n",ans); 40 } 41 return 0; 42 }
E - Queue
There are n walruses standing in a queue in an airport. They are numbered starting from the queue's tail: the 1-st walrus stands at the end of the queue and the n-th walrus stands at the beginning of the queue. The i-th walrus has the age equal to ai.
The i-th walrus becomes displeased if there's a younger walrus standing in front of him, that is, if exists such j (i < j), that ai > aj. The displeasure of the i-th walrus is equal to the number of walruses between him and the furthest walrus ahead of him, which is younger than the i-th one. That is, the further that young walrus stands from him, the stronger the displeasure is.
The airport manager asked you to count for each of n walruses in the queue his displeasure.
Input
The first line contains an integer n (2 ≤ n ≤ 105) — the number of walruses in the queue. The second line contains integers ai (1 ≤ ai ≤ 109).
Note that some walruses can have the same age but for the displeasure to emerge the walrus that is closer to the head of the queue needs to be strictly younger than the other one.
Output
Print n numbers: if the i-th walrus is pleased with everything, print "-1" (without the quotes). Otherwise, print the i-th walrus's displeasure: the number of other walruses that stand between him and the furthest from him younger walrus.
Examples
6
10 8 5 3 50 45
2 1 0 -1 0 -1
7
10 4 6 3 2 8 15
4 2 1 0 -1 -1 -1
5
10 3 1 10 11
1 0 -1 -1 -1
题意:求出对于每个元素来说在自己右边且比自己小的元素离自己的最远距离
题解:维护一个单调栈,然后就可以二分单调栈求出最远的比自己小的元素
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<queue> 5 #include<set> 6 #include<map> 7 #include<stack> 8 #include<vector> 9 #include<cmath> 10 #include<algorithm> 11 using namespace std; 12 typedef long long ll; 13 #define debug(x,y,z) cout<< #x <<" is "<<x<<" "<< #y <<" is "<<y<<" "<< #z <<" is "<<z<<endl; 14 #define debugs(x) cout<< #x <<" is "<<x<<endl; 15 int a[100005],b[100005],c[100005],d[100005]; 16 int main() 17 { 18 int n; 19 scanf("%d",&n); 20 for(int i=1;i<=n;i++)scanf("%d",&a[i]); 21 //int head=1; 22 int tail=0; 23 for(int i=n;i>=1;i--){ 24 if(tail==0||-b[tail]>=a[i]){ 25 c[i]=-1; 26 b[++tail]=-a[i]; 27 d[tail]=i; 28 } 29 else{ 30 int pos=upper_bound(b+1,b+1+tail,-a[i])-b; 31 c[i]=d[pos]-i-1; 32 } 33 } 34 for(int i=1;i<=n;i++){ 35 printf("%d",c[i]); 36 char cc=(i==n)?'\n':' '; 37 printf("%c",cc); 38 } 39 return 0; 40 }
F - Watching Fireworks is Fun
A festival will be held in a town's main street. There are n sections in the main street. The sections are numbered 1 through n from left to right. The distance between each adjacent sections is 1.
In the festival m fireworks will be launched. The i-th (1 ≤ i ≤ m) launching is on time ti at section ai. If you are at section x (1 ≤ x ≤ n) at the time of i-th launching, you'll gain happiness value bi - |ai - x| (note that the happiness value might be a negative value).
You can move up to d length units in a unit time interval, but it's prohibited to go out of the main street. Also you can be in an arbitrary section at initial time moment (time equals to 1), and want to maximize the sum of happiness that can be gained from watching fireworks. Find the maximum total happiness.
Note that two or more fireworks can be launched at the same time.
Input
The first line contains three integers n, m, d (1 ≤ n ≤ 150000; 1 ≤ m ≤ 300; 1 ≤ d ≤ n).
Each of the next m lines contains integers ai, bi, ti (1 ≤ ai ≤ n; 1 ≤ bi ≤ 109; 1 ≤ ti ≤ 109). The i-th line contains description of the i-th launching.
It is guaranteed that the condition ti ≤ ti + 1 (1 ≤ i < m) will be satisfied.
Output
Print a single integer — the maximum sum of happiness that you can gain from watching all the fireworks.
Please, do not write the %lld specifier to read or write 64-bit integers in C++. It is preferred to use the cin, cout streams or the %I64d specifier.
Examples
50 3 1
49 1 1
26 1 4
6 1 10
-31
10 2 1
1 1000 4
9 1000 4
1992
题意:有m种烟花,每种烟花有一个最佳观看地点ai,在x处观看烟花得到的快乐值为 bi-abs(ai-x),释放时刻为ti,你的初始位置可以是1~n的任意点,每秒可以移动d米,求欢乐值之和的最大值
题解:设dp[i][j]表示在j处观看第i种烟花的最大值,则dp[i][j]=max(dp[i-1][k])+b[i]-abs(a[i]-j) 其中(a[i]-(t[i]-t[i-1])*d<=k<=a[i]+(t[i]-t[i-1])*d),所以可以使用单调队列加速dp
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<queue> 5 #include<set> 6 #include<map> 7 #include<stack> 8 #include<vector> 9 #include<cmath> 10 #include<algorithm> 11 using namespace std; 12 typedef long long ll; 13 #define debug(x,y,z) cout<< #x <<" is "<<x<<" "<< #y <<" is "<<y<<" "<< #z <<" is "<<z<<endl; 14 #define debugs(x) cout<< #x <<" is "<<x<<endl; 15 struct pot{ 16 ll tim; 17 ll a; 18 ll b; 19 }p[305]; 20 int q[150005],w[150005]; 21 ll dp[2][150005]; 22 map<int,int>mp; 23 const ll inf=1e18; 24 int main() 25 { 26 int n,m,d; 27 scanf("%d%d%d",&n,&m,&d); 28 int tot=0; 29 for(int i=1;i<=m;i++){ 30 scanf("%I64d%I64d%I64d",&p[i].a,&p[i].b,&p[i].tim); 31 if(!mp[p[i].tim])mp[p[i].tim]=++tot; 32 } 33 ll ans=-inf; 34 int t=-1; 35 int id=0; 36 for(int i=1;i<=m;i++){ 37 int head=1; 38 int tail=0; 39 int k=1; 40 if(p[i].tim==t){ 41 for(int j=1;j<=n;j++){ 42 dp[id][j]=dp[id^1][j]+p[i].b-abs(p[i].a-j); 43 } 44 } 45 else{ 46 for(int j=1;j<=n;j++){ 47 dp[id][j]=-inf; 48 while(k<=n&&k<=j+(p[i].tim-t)*d){ 49 while(head<=tail&&dp[id^1][k]>dp[id^1][q[tail]])tail--; 50 q[++tail]=k; 51 k++; 52 } 53 while(head<=tail&&q[head]<j-(p[i].tim-t)*d)head++; 54 if(head<=tail)dp[id][j]=dp[id^1][q[head]]+p[i].b-abs(p[i].a-j); 55 } 56 t=p[i].tim; 57 } 58 id^=1; 59 } 60 for(int i=1;i<=n;i++){ 61 // debugs(dp[m][i]); 62 ans=max(dp[id^1][i],ans); 63 } 64 printf("%I64d\n",ans); 65 return 0; 66 }