看洛谷网校学习的安全
例题:学习
T1:向右看齐Look Up 单调栈裸题
T2:POJ3250 Bad Hair Day 单调栈裸题
T3:考虑第i位为最小值来更新答案,用单调栈维护出左边第一个大于他的位置,和右边第一个大于他的位置便可。
T4:先贪心考虑以第i个矩形为基础的矩形有多大,而后用单调栈维护便可。
T5:在最优策略下,非最大值的数,必定是与它左右第一个比它大的数中较小的那个替代的。
T6:考虑第i位是最小值,而后二进制拆位计算方案数。
T7:考虑枚举每一点,而后每一点横向能扩展到哪里,而后跟T4差很少了
T8:不会
把一些难写的题放上来吧。spa
int a[maxN], b[maxN], c[maxN]; int sta[maxN] , top; int main() { int n = gi(); a[0] = INF;a[n + 1] = INF; for(int i = 1;i <= n;++ i) a[i] = gi(); for(int i = n;i >= 1;-- i) { while(top && a[sta[top]] < a[i]) { b[sta[top --]] = i; } sta[++ top] = i; } for(int i = 1;i <= n;++ i) { while(top && a[sta[top]] <= a[i]) { c[sta[top --]] = i; } sta[++ top] = i; } ll ans = 0; for(int i = 1;i <= n;++ i) { int x = min(a[b[i]] , a[c[i]]); if(x != INF) ans += x; } printf("%lld",ans); return 0; }
int a[maxN], b[maxN], c[maxN]; int sta[maxN] , top; int main() { int n = gi(); a[0] = INF;a[n + 1] = INF; for(int i = 1;i <= n;++ i) a[i] = gi(); for(int i = n;i >= 1;-- i) { while(top && a[sta[top]] < a[i]) { b[sta[top --]] = i; } sta[++ top] = i; } top = 0; for(int i = 1;i <= n;++ i) { while(top && a[sta[top]] <= a[i]) { c[sta[top --]] = i; } sta[++ top] = i; } ll ans = 0; for(int i = 1;i <= n;++ i) { int x = min(a[b[i]] , a[c[i]]); if(x != INF) ans += x; } printf("%lld",ans); return 0; }
int a[N] , sum[N] , c[N][30] , lp[N] , rp[N] , sta[N] , tot; int main() { int T; scanf("%d" , &T); while(T -- ) { int n , i , j , ans = 0; scanf("%d" , &n); memset(c , 0 , sizeof(c)); for(i = 2 ; i <= n + 1 ; i ++ ) { scanf("%d" , &a[i]) , sum[i] = sum[i - 1] ^ a[i]; for(j = 0 ; j < 30 ; j ++ ) c[i][j] = c[i - 1][j] + (bool)(sum[i] & (1 << j)); } tot = 0 , sta[0] = 1; for(i = 2 ; i <= n + 1 ; i ++ ) { while(tot && a[sta[tot]] < a[i]) tot -- ; lp[i] = sta[tot] , sta[++ tot] = i; } tot = 0 , sta[0] = n + 2; for(i = n + 1 ; i >= 2 ; i -- ) { while(tot && a[sta[tot]] <= a[i]) tot -- ; rp[i] = sta[tot] , sta[++tot] = i; } for(i = 2 ; i <= n + 1 ; i ++ ) for(j = 0 ; j < 30 ; j ++ ) ans = (ans + ((ll)(c[i - 1][j] - c[lp[i] - 1][j]) * (rp[i] - i - c[rp[i] - 1][j] + c[i - 1][j]) + (ll)(i - lp[i] - c[i - 1][j] + c[lp[i] - 1][j]) * (c[rp[i] - 1][j] - c[i - 1][j])) % mod * (1 << j) % mod * a[i]) % mod; printf("%d\n" , ans); } return 0; }
Largest Rectangle in a Histogramcode
using namespace std; int a[N][N] , sta[N] , tot , lp[N] , rp[N]; char str[5]; int main() { int n , m , i , j , ans = 0; scanf("%d%d" , &n , &m); for(i = 1 ; i <= n ; i ++ ) { for(j = 1 ; j <= m ; j ++ ) { scanf("%s" , str); if(str[0] == 'F') a[i][j] = a[i - 1][j] + 1; } tot = 0 , sta[0] = 0; for(j = 1 ; j <= m ; j ++ ) { while(tot && a[i][j] <= a[i][sta[tot]]) tot -- ; lp[j] = sta[tot] , sta[++tot] = j; } tot = 0 , sta[tot] = m + 1; for(j = m ; j ; j -- ) { while(tot && a[i][j] <= a[i][sta[tot]]) tot -- ; rp[j] = sta[tot] , sta[++tot] = j; } for(j = 1 ; j <= m ; j ++ ) ans = max(ans , a[i][j] * (rp[j] - lp[j] - 1)); } printf("%d\n" , ans * 3); return 0; }