17-09-01模拟赛

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:

原文地址:https://www.cnblogs.com/codingutopia/p/test170901.html