判斷是否合法便可,合法是\(2^{\lfloor \frac{N}{2}\rfloor}\)node
不合法就是0ios
#include <bits/stdc++.h> #define fi first #define se second #define pii pair<int,int> #define mp make_pair #define pb push_back #define space putchar(' ') #define enter putchar('\n') #define eps 1e-10 #define MAXN 200005 //#define ivorysi using namespace std; typedef long long int64; typedef unsigned int u32; typedef double db; template<class T> void read(T &res) { res = 0;T f = 1;char c = getchar(); while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { res = res * 10 +c - '0'; c = getchar(); } res *= f; } template<class T> void out(T x) { if(x < 0) {x = -x;putchar('-');} if(x >= 10) { out(x / 10); } putchar('0' + x % 10); } const int MOD = 1000000007; int N; int cnt[MAXN]; int inc(int a,int b) { return a + b >= MOD ? a + b - MOD : a + b; } int mul(int a,int b) { return 1LL * a * b % MOD; } int fpow(int x,int c) { int res = 1,t = x; while(c) { if(c & 1) res = mul(res,t); t = mul(t,t); c >>= 1; } return res; } void Solve() { read(N); int a; for(int i = 1 ; i <= N ; ++i) { read(a);cnt[a]++; } if(N & 1) { if(cnt[0] != 1) {puts("0");return;} } for(int i = N - 1 ; i >= 1 ; i -= 2) { if(cnt[i] != 2) { puts("0");return; } } out(fpow(2,N / 2));enter; } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); return 0; }
按位dp,每一位的兩個數要麼就是1 1,要麼就是1 0(不分順序),要麼就是0 0c++
能夠發現,這三種狀況若是有一位上是不一樣的,那算出來的是不一樣的u和v優化
而後咱們能夠限制兩個數的和每一位是多少來dp,由於和確定大於異或和spa
設\(dp[i][0 / 1][0/1]\)表示前i位,和有沒有碰到上界,前面的和需不須要進位code
#include <bits/stdc++.h> #define fi first #define se second #define pii pair<int,int> #define mp make_pair #define pb push_back #define space putchar(' ') #define enter putchar('\n') #define eps 1e-10 #define MAXN 200005 //#define ivorysi using namespace std; typedef long long int64; typedef unsigned int u32; typedef double db; template<class T> void read(T &res) { res = 0;T f = 1;char c = getchar(); while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { res = res * 10 +c - '0'; c = getchar(); } res *= f; } template<class T> void out(T x) { if(x < 0) {x = -x;putchar('-');} if(x >= 10) { out(x / 10); } putchar('0' + x % 10); } const int MOD = 1000000007; int64 N; int dp[65][2][2]; int inc(int a,int b) { return a + b >= MOD ? a + b - MOD : a + b; } int mul(int a,int b) { return 1LL * a * b % MOD; } void update(int &x,int y) { x = inc(x,y); } void Solve() { read(N); dp[61][1][0] = 1; for(int i = 60 ; i >= 0 ; --i) { for(int j = 0 ; j < 2 ; ++j) { for(int k = 0 ; k < 2 ; ++k) { int t = (N >> i) & 1,u; u = t; if(j == 0) u = 1; for(int h = 0 ; h <= u ; ++h) { int p = j && (h == t); if(k) { if(h == 0){ update(dp[i][p][1],dp[i + 1][j][k]); update(dp[i][p][0],dp[i + 1][j][k]); } else { update(dp[i][p][1],dp[i + 1][j][k]); } } else { if(h == 0) { update(dp[i][p][0],dp[i + 1][j][k]); } else { update(dp[i][p][1],dp[i + 1][j][k]); update(dp[i][p][0],dp[i + 1][j][k]); } } } } } } int ans = 0; for(int j = 0 ; j < 2 ; ++j) { update(ans,dp[0][j][0]); } out(ans);enter; } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); return 0; }
發現括號嵌套超過三個總能夠改爲嵌套兩個get
而後咱們就能夠設\(dp[i][j]\)表示第i位以前有j個沒閉合的括號,有一個括號符號改變一次正反,咱們只能在初始符號是減號的地方加括號,由於加號的後面加括號沒什麼用string
#include <bits/stdc++.h> #define fi first #define se second #define pii pair<int,int> #define mp make_pair #define pb push_back #define space putchar(' ') #define enter putchar('\n') #define eps 1e-10 #define MAXN 100005 //#define ivorysi using namespace std; typedef long long int64; typedef unsigned int u32; typedef double db; template<class T> void read(T &res) { res = 0;T f = 1;char c = getchar(); while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { res = res * 10 +c - '0'; c = getchar(); } res *= f; } template<class T> void out(T x) { if(x < 0) {x = -x;putchar('-');} if(x >= 10) { out(x / 10); } putchar('0' + x % 10); } int N; int64 dp[MAXN][3]; int64 A[MAXN]; char op[MAXN][5]; void update(int64 &x,int64 y) { x = max(x,y); } void Solve() { read(N); for(int i = 1 ; i <= N ; ++i) { read(A[i]); if(i != N) scanf("%s",op[i] + 1); } dp[1][0] = A[1]; dp[1][1] = -1e18; dp[1][2] = -1e18; for(int i = 2 ; i <= N ; ++i) { for(int j = 0 ; j < 3 ; ++j) dp[i][j] = -1e18; for(int j = 0 ; j < 3 ; ++j) { int t = (op[i - 1][1] == '-'); int k = (t ^ j) & 1; int64 d = A[i]; if(k) d = -A[i]; if(t && j < 2) update(dp[i][j + 1],dp[i - 1][j] + d); for(int h = 0 ; h <= j ; ++h) update(dp[i][h],dp[i - 1][j] + d); } } out(dp[N][0]);enter; } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); return 0; }
(以前的題解)it
我寫的斜率維護,放棄了我最擅長的叉積維護,而後發現叉積維護也不會爆long long哦……io
一寫斜率維護個人代碼就會莫名變長並且難寫……行吧
咱們看這題
推了推式子,發現這是個斜率的式子,可是斜率單增還要求最大值?啥我又得二分凸包……好煩……
而後咱們求一個pre[x]表示[1,x]的最大分數,和一個suf[x]表示[x,N]裏的最大分數
而後對於一個點枚舉一個包含它的區間,計算取值
顯然超時
那就放在分治上,左端點在左區間,右端點在右區間,把最大值處理成先後綴max,兩邊都是斜率優化
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <cmath> #define fi first #define se second #define pii pair<int,int> //#define ivorysi #define mp make_pair #define pb push_back #define enter putchar('\n') #define space putchar(' ') #define MAXN 300005 using namespace std; typedef long long int64; typedef double db; typedef unsigned int u32; template<class T> void read(T &res) { res = 0;T f = 1;char c = getchar(); while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9' ) { res = res * 10 + c - '0'; c = getchar(); } res *= f; } template<class T> void out(T x) { if(x < 0) {x = -x;putchar('-');} if(x >= 10) { out(x / 10); } putchar('0' + x % 10); } int N,M; int64 T[MAXN],pre[MAXN],suf[MAXN],sum[MAXN],ans[MAXN],cal[MAXN]; struct Point { int64 x,y; Point(){} Point(int64 _x,int64 _y) { x = _x;y = _y; } }que[MAXN],pre_pos[MAXN],suf_pos[MAXN]; struct qry_node { int id,pos; int64 v; }qry[MAXN],tmp1[MAXN],tmp2[MAXN]; bool slope(Point a,Point b,Point c) { return (c.y - b.y) * (b.x - a.x) > (b.y - a.y) * (c.x - b.x); } void DC(int l,int r,int ql,int qr) { if(qr < ql) return; if(l == r) return; int mid = (l + r) >> 1; int tot = 0; que[++tot] = pre_pos[l - 1]; for(int i = l ; i <= mid ; ++i) { while(tot > 1) { if(slope(que[tot - 1],que[tot],pre_pos[i])) --tot; else break; } que[++tot] = pre_pos[i]; } for(int i = r + 1 ; i >= mid + 2; --i) { int L = 1,R = tot; while(L < R) { int mid = (L + R) >> 1; if((que[mid + 1].y - que[mid].y) >= 1LL * i * (que[mid + 1].x - que[mid].x)) L = mid + 1; else R = mid; } L = que[L].x; cal[i] = suf[i] + pre[L] - sum[i - 1] + sum[L] + 1LL * (i - L - 1) * (i - L) / 2; } tot = 0; que[++tot] = suf_pos[r + 1]; for(int i = r ; i > mid ; --i) { while(tot > 1) { if(slope(suf_pos[i],que[tot],que[tot - 1])) --tot; else break; } que[++tot] = suf_pos[i]; } for(int i = l - 1 ; i < mid ; ++i) { int L = 1,R = tot; while(L < R) { int mid = (L + R) >> 1; if((que[mid].y - que[mid + 1].y) >= 1LL * i * (que[mid].x - que[mid + 1].x)) R = mid; else L = mid + 1; } L = que[L].x; cal[i] = pre[i] + suf[L] - sum[L - 1] + sum[i] + 1LL * (L - i - 1) * (L - i) / 2; } for(int i = l ; i < mid ; ++i) cal[i] = max(cal[i - 1],cal[i]); for(int i = r ; i > mid + 1 ; --i) cal[i] = max(cal[i + 1],cal[i]); int t1 = 0,t2 = 0; for(int i = ql ; i <= qr ; ++i) { if(qry[i].pos <= mid) { ans[qry[i].id] = max(ans[qry[i].id],cal[qry[i].pos - 1] + T[qry[i].pos] - qry[i].v); tmp1[++t1] = qry[i]; } else { ans[qry[i].id] = max(ans[qry[i].id],cal[qry[i].pos + 1] + T[qry[i].pos] - qry[i].v); tmp2[++t2] = qry[i]; } } int p = ql - 1; for(int i = 1 ; i <= t1 ; ++i) qry[++p] = tmp1[i]; for(int i = 1 ; i <= t2 ; ++i) qry[++p] = tmp2[i]; DC(l,mid,ql,ql + t1 - 1); DC(mid + 1,r,ql + t1,qr); } void Solve() { read(N); for(int i = 1 ; i <= N ; ++i) read(T[i]); for(int i = 1 ; i <= N ; ++i) sum[i] = sum[i - 1] + T[i]; int tot = 0; que[++tot] = Point(0,0); for(int i = 1 ; i <= N ; ++i) { int l = 1,r = tot; while(l < r) { int mid = (l + r) >> 1; if((que[mid + 1].y - que[mid].y) >= 1LL * i * (que[mid + 1].x - que[mid].x)) l = mid + 1; else r = mid; } l = que[l].x; pre[i] = pre[l] + 1LL * (i - l) * (i - l + 1) / 2 - sum[i] + sum[l]; pre[i] = max(pre[i],pre[i - 1]); Point p = Point(i,pre[i] + sum[i] + (1LL * i * (i - 1)) / 2); while(tot > 1) { if(slope(que[tot - 1],que[tot],p)) --tot; else break; } que[++tot] = p; } tot = 0; que[++tot] = Point(N + 1,(1LL * (N + 1) * (N + 2) / 2) - sum[N]); for(int i = N ; i >= 1 ; --i) { int l = 1,r = tot; while(l < r) { int mid = (l + r) >> 1; if((que[mid].y - que[mid + 1].y) >= 1LL * i * (que[mid].x - que[mid + 1].x)) r = mid; else l = mid + 1; } l = que[l].x; suf[i] = suf[l] + (1LL * (l - i + 1) * (l - i) / 2) - sum[l - 1] + sum[i - 1]; suf[i] = max(suf[i],suf[i + 1]); Point p = Point(i,suf[i] - sum[i - 1] + (1LL * i * (i + 1) / 2)); while(tot > 1) { if(slope(p,que[tot],que[tot - 1])) --tot; else break; } que[++tot] = p; } for(int i = 0 ; i <= N ; ++i) { pre_pos[i] = Point(i,pre[i] + sum[i] + (1LL * i * (i + 1) / 2)); } for(int i = 1 ; i <= N + 1 ; ++i) { suf_pos[i] = Point(i,suf[i] - sum[i - 1] + (1LL * i * (i - 1) / 2)); } read(M); int p;int64 v; for(int i = 1 ; i <= M ; ++i) { read(p);read(v); qry[i] = (qry_node){i,p,v}; ans[i] = pre[p - 1] + suf[p + 1]; } DC(1,N,1,M); for(int i = 1 ; i <= M ; ++i) { out(ans[i]);enter; } } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); return 0; }