T1:模拟加+进位操作时间复杂度为O(n log n),但对于109的数据,正常开数组会MLE.
考虑用(unsigned) int 压位。将32位压至一个数中,只要开约3.2*107的数组即可,空间复杂度小于128MB.
Code:
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define MN 40000005 5 #define ll long long 6 using namespace std; 7 inline int in(){ 8 int x=0;bool f=0; char c; 9 for (;(c=getchar())<'0'||c>'9';f=c=='-'); 10 for (x=c-'0';(c=getchar())>='0'&&c<='9';x=(x<<3)+(x<<1)+c-'0'); 11 return f?-x:x; 12 } 13 unsigned int a[MN],n,tp,x,y; 14 inline void add(int x,int y){ 15 16 ll sum=1ll*a[x]+y;a[x]=sum&((1ll<<32)-1); 17 if (sum>=1ll<<32) add(x+1,sum>>32); 18 } 19 inline bool query(int x){ 20 int pos=x&31,cur=x>>5;return (bool)(a[cur]&(1ll<<pos)); 21 } 22 int main () 23 { 24 n=in();for (int i=1;i<=n;++i){ 25 tp=in();x=in(); 26 if (tp==1){ 27 y=in();int pos=y&31,cnt=y>>5; 28 add(cnt,(x&((1ll<<32-pos)-1))<<pos); 29 if (pos) add(cnt+1,x>>(32-pos)); 30 } 31 else printf("%d ",query(x)); 32 }return 0; 33 }
T2:通过题意容易想到用树链剖分+线段树操作解决。但最坏时间复杂度为O(m log n),update:O(m log2 n),对于n,m<=5*105的数据在时限为1.5s会超时。
考虑通过差分解决。给一条从x到y的链加上v的操作可以看做分别给x和y到根的路径加上v,然后给z(即lca(x,y))到根的路径加上-v,给z的父亲(若有)到根的路径加上-v.
注意到一个点会被影响当且仅当修改的点在它的子树内。
考虑对树求dfs序,然后使用线段树单点加,区间查询(查询该点的dfs序与该点子树中的点的最大dfs序)即可,复杂度O(n log n)。
Code:
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define L (x<<1) 5 #define R (x<<1|1) 6 #define MN 500005 7 #define Lg 20 8 using namespace std; 9 inline int in(){ 10 int x=0;bool f=0; char c; 11 for (;(c=getchar())<'0'||c>'9';f=c=='-'); 12 for (x=c-'0';(c=getchar())>='0'&&c<='9';x=(x<<3)+(x<<1)+c-'0'); 13 return f?-x:x; 14 } 15 struct edge{ 16 int to,next; 17 }e[MN<<1]; 18 int head[MN],dep[MN],fa[MN][Lg],pos[MN],rps[MN],val[MN],sum[(1<<Lg)+5]; 19 int cnt=0,dfsn=0,M=0,a,b,v,x,y,k,tp,n,m; 20 inline void ins(int x,int y){ 21 e[++cnt].to=y;e[cnt].next=head[x];head[x]=cnt; 22 } 23 inline void swap(int &a,int &b){a^=b;b^=a;a^=b;} 24 inline void dfs(int u){ 25 pos[u]=(++dfsn); 26 for (int i=head[u];i;i=e[i].next){ 27 int v=e[i].to;if (fa[u][0]==v) continue; 28 dep[v]=dep[u]+1;fa[v][0]=u;dfs(v); 29 }rps[u]=dfsn; 30 } 31 inline void getfa(){ 32 for (int j=1;j<=Lg;++j) 33 for (int i=1;i<=n;++i) fa[i][j]=fa[fa[i][j-1]][j-1]; 34 } 35 inline int getlca(int u,int v){ 36 if (dep[u]<dep[v]) swap(u,v);int dif=dep[u]-dep[v]; 37 for (int i=0;i<Lg;++i)if (dif&(1<<i)) u=fa[u][i];if (u==v) return u; 38 for (int i=Lg-1;i>=0;--i) 39 if (fa[u][i]!=fa[v][i]) u=fa[u][i],v=fa[v][i];u=fa[u][0];return u; 40 } 41 inline void add(int x,int v){ 42 sum[x+=M]+=v;for (x>>=1;x;x>>=1) sum[x]=sum[L]+sum[R]; 43 } 44 inline int query(int l,int r){ 45 int res=0; 46 for (l+=M-1,r+=M+1;l^r^1;l>>=1,r>>=1){ 47 if (~l&1) res+=sum[l^1]; 48 if ( r&1) res+=sum[r^1]; 49 }return res; 50 } 51 int main() 52 { 53 freopen("tree.in","r",stdin);freopen("tree.out","w",stdout); 54 n=in();m=in();for (M=1;M<n+2;M<<=1); 55 for (int i=1;i<=n;++i) val[i]=in(); 56 for (int i=1;i<n;++i){x=in();y=in();ins(x,y);ins(y,x);} 57 fa[1][0]=0;dfs(1);getfa(); 58 for (int i=1;i<=m;++i){ 59 tp=in();if (tp==1){ 60 a=in();b=in();v=in();add(pos[a],v);add(pos[b],v); 61 int lca=getlca(a,b);add(pos[lca],-v); 62 if (fa[lca][0]) add(pos[fa[lca][0]],-v); 63 }else k=in(),printf("%d ",query(pos[k],rps[k])+val[k]); 64 }return 0; 65 }
T3: