A:
This question is still very simple and has been done many times, similar to the problem of board cutting.
Put all the numbers in a priority queue, bring up two largest ones, and then merge them to put the results in. .
#include <iostream>#include<stdio.h>#include<stdlib.h>#include<time.h>#include<vector>#include<algorithm>#include<string.h>#include<queue>using namespace std;#define LL __int64#define INF 1000000000LL a[330000];priority_queue<LL>que;int main(){ int n; while(~scanf("%d",&n)) { LL sum=0; while(!que.empty())que.pop(); for(int i=1;i<=n;i++) { scanf("%I64d",&a[i]); sum+=a[i]; que.push(a[i]); } LL ans=0; while(!que.empty()) { LL x=que.top(); que.pop(); if(!que.empty()) { LL y=que.top(); que.pop(); ans+=x; ans+=y; que.push(x+y); } else { ans+=x; break; } } cout<<ans<<endl; } return 0;}
B: tree-like DP
DP [I] [0]: number of cases where the contribution of the subtree with an I node as the root is 0
DP [I] [1]: number of situations where the contribution of the subtree with the I node as the root is 1
If the I node is 0
Obviously for DP [I] [1]:
Which subtree contributes 1 to I? If A, B, and C are the subtree of I
DP [I] [1] = DP [a] [1] * DP [B] [0] * DP [C] [0] + dp [a] [0] * DP [B] [1] * DP [C] [0] + dp [a] [0] * DP [B] [0] * DP [C] [1];
For DP [I] [0]:
1. If all subtree does not contribute to I
DP [I] [0] + = DP [a] [0] * DP [B] [0] * DP [C] [0];
2. There is a subtree that contributes 1 to I, but the edge above the I node is cut off.
DP [I] [0] + = DP [I] [1];
If the I node is 1
DP [I] [0] = DP [I] [1] = DP [a] [0] * DP [B] [0] * DP [C] [0];
# Include <iostream> # include <stdio. h> # include <string. h> # include <algorithm> # include <iostream> # include <vector> # include <set> # include <string> using namespace STD; # define maxn 110000 # define ll _ int64 # define mod 1000000007 vector <int> old [maxn]; vector <int> now [maxn]; int vis [maxn]; void change (int x) {int I; vis [x] = 1; for (I = 0; I <old [X]. size (); I ++) {If (vis [old [x] [I]) continue; now [X]. push_back (old [x] [I]); Chan Ge (old [x] [I]) ;}} ll DP [maxn] [2]; int A [maxn]; ll q_mod (ll a, LL B, ll N) {ll ret = 1; ll TMP = A; while (B) {// If (B & 0x1) ret = RET * TMP % N; TMP = TMP * TMP % N; B >>= 1;} return ret;} ll DoS (LL X, ll y, ll Z) {x = x * z; X = x % MOD; X = x * q_mod (Y, mod-2, MoD); X = x % MOD; return X;} void DFS (int x) {int leap = 0; ll sum = 1; for (INT I = 0; I <now [X]. size (); I ++) {DFS (now [x] [I]); leap = 1; sum = sum * DP [now [x] [I] [0]; sum = sum % MOD;} If (leap = 0) {if (a [x] = 0) {DP [x] [0] = 1; DP [x] [1] = 0 ;} else {DP [x] [1] = 1; DP [x] [0] = 1 ;} // cout <x <"" <DP [x] [1] <"" <DP [x] [0] <Endl; return ;} if (A [x] = 0) {DP [x] [0] = sum; DP [x] [1] = 0; For (INT I = 0; I <now [X]. size (); I ++) {int y = now [x] [I]; DP [x] [1] + = DoS (sum, DP [y] [0], DP [y] [1]); DP [x] [1] % = MOD ;} DP [x] [0] + = DP [x] [1]; DP [x] [0] % = MOD ;} else {DP [x] [1] = sum; DP [x] [0] = sum ;} // cout <x <"<DP [x] [1] <" "<DP [x] [0] <Endl ;}int main () {int I, n, J; int AA, AB; while (~ Scanf ("% d", & N) {memset (VIS, 0, sizeof (VIS); for (I = 0; I <= N; I ++) {old [I]. clear (); now [I]. clear () ;}for (I = 1; I <n; I ++) {scanf ("% d", & aa); AA = AA + 1; AB = I + 1; // cout <"" <AA <"-" <AB <Endl; old [AA]. push_back (AB); old [AB]. push_back (AA) ;}for (INT I = 1; I <= N; I ++) scanf ("% d", & A [I]); change (1); DFS (1); cout <DP [1] [1] <Endl;} return 0 ;}
C:
Obviously, if you flip more than half of it, it is equivalent to first rotating and then turning the rest.
Then we can flip 2 * n digits at most. Then, the current status is enumerated.
Then, we use the line segment tree to store the length of each node, and then sum the intervals when asking.
#include<iostream>#include<stdio.h>#include<string.h>#include<algorithm>#include<iostream>#include<vector>#include<set>#include<string>using namespace std;#define maxn 110000#define LL __int64#define mod 1000000007#define mem(a,b) (memset(a),b,sizeof(a))#define lmin 1#define rmax n#define lson l,(l+r)/2,rt<<1#define rson (l+r)/2+1,r,rt<<1|1#define root lmin,rmax,1#define now l,r,rt#define int_now int l,int r,int rtint have[maxn];int sum[maxn<<2];void creat(int_now){ if(l!=r) { creat(lson); creat(rson); sum[rt]=sum[rt<<1]+sum[rt<<1|1]; } else { sum[rt]=1; }}void updata(int ll,int x,int_now){ if(ll>r||ll<l)return; if(ll==l&&l==r) { sum[rt]=x; return ; } updata(ll,x,lson); updata(ll,x,rson); sum[rt]=sum[rt<<1]+sum[rt<<1|1];}int query(int ll,int rr,int_now){ if(ll>r||rr<l)return 0; if(ll<=l&&rr>=r)return sum[rt]; return query(ll,rr,lson)+query(ll,rr,rson);}int leap,st,ed,n;void chu(int p){ if(leap==0) { st=st+p; ed=ed; for(int i=p; i>=1; i--) { have[st+i-1]=have[st+i-1]+have[st-i]; updata(st+i-1,have[st+i-1],root); } } else { ed=ed-p; st=st; for(int i=p; i>=1; i--) { have[ed-i+1]=have[ed-i+1]+have[ed+i]; updata(ed-i+1,have[ed-i+1],root); } }}int main(){ int q; while(~scanf("%d%d",&n,&q)) { creat(root); for(int i=1; i<=n; i++)have[i]=1; int len=n; leap=0; st=1; ed=n; int a,b,p,t; while(q--) { scanf("%d",&t); if(t==1) { scanf("%d",&p); len=ed-st+1; int ban=len/2; if(p<=ban) { chu(p); } else { len=ed-st+1; p=len-p; leap=leap^1; chu(p); } } else { scanf("%d%d",&a,&b); if(leap==0) { a=a+st; b=b+st-1; } else { a=ed-a; b=ed-b+1; swap(a,b); } if(a>ed||b<st) { cout<<"0"<<endl; continue; } if(b>ed)b=ed; if(a<st)a=st; cout<<query(a,b,root)<<endl; } } } return 0;}
Codeforces round #263 (Div. 1)-a, B, c