我太弱了只能做做poi水题。
那就按总AC数倒叙做吧。
诶怎么还是有好多不会的。
[POI2007]MEG-Megalopolis
题意:https://www.luogu.org/problemnew/show/P3459
分析:发现查询的起点总是1。把边下放到点,树剖裸上。注意1号点是不要的。
代码:
1 #include <stdio.h> 2 #include <string.h> 3 #include <algorithm> 4 using namespace std; 5 #define N 250050 6 #define lson pos<<1 7 #define rson pos<<1|1 8 int head[N],to[N<<1],nxt[N<<1],cnt,tot; 9 int n,m,dep[N],fa[N],son[N],siz[N],top[N],idx[N]; 10 int t[N<<2]; 11 char ch[10]; 12 void read(int &x) 13 { 14 int f=1;x=0;char s=getchar(); 15 while(s<‘0‘||s>‘9‘){if(s==‘-‘)f=-1;s=getchar();} 16 while(s>=‘0‘&&s<=‘9‘){x=(x<<3)+(x<<1)+s-‘0‘;s=getchar();} 17 x*=f; 18 } 19 inline void add(int u,int v) 20 { 21 to[++cnt]=v; 22 nxt[cnt]=head[u]; 23 head[u]=cnt; 24 } 25 void dfs1(int x,int y) 26 { 27 dep[x]=dep[y]+1; 28 fa[x]=y; 29 siz[x]=1; 30 for(int i=head[x];i;i=nxt[i]) 31 { 32 if(to[i]==y)continue; 33 dfs1(to[i],x); 34 siz[x]+=siz[to[i]]; 35 if(siz[to[i]]>siz[son[x]]) 36 { 37 son[x]=to[i]; 38 } 39 } 40 } 41 void dfs2(int x,int t) 42 { 43 top[x]=t;idx[x]=++tot; 44 if(son[x])dfs2(son[x],t); 45 for(int i=head[x];i;i=nxt[i]) 46 { 47 if(to[i]==fa[x]||to[i]==son[x])continue; 48 dfs2(to[i],to[i]); 49 } 50 } 51 void bt(int l,int r,int pos) 52 { 53 if(l==r) 54 { 55 t[pos]=1;return ; 56 } 57 int mid=l+r>>1; 58 bt(l,mid,lson); 59 bt(mid+1,r,rson); 60 t[pos]=t[lson]+t[rson]; 61 } 62 void up(int l,int r,int x,int y,int pos) 63 { 64 if(t[pos]==0)return ; 65 if(x<=l&&r<=y) 66 { 67 t[pos]=0;return ; 68 } 69 int mid=l+r>>1; 70 if(x<=mid)up(l,mid,x,y,lson); 71 if(y>mid)up(mid+1,r,x,y,rson); 72 t[pos]=t[lson]+t[rson]; 73 } 74 int query(int l,int r,int x,int y,int pos) 75 { 76 if(x<=l&&r<=y)return t[pos]; 77 int re=0,mid=l+r>>1; 78 if(x<=mid)re+=query(l,mid,x,y,lson); 79 if(y>mid)re+=query(mid+1,r,x,y,rson); 80 return re; 81 } 82 int main() 83 { 84 scanf("%d",&n); 85 bt(1,n,1); 86 int x,y; 87 for(int i=1;i<n;i++) 88 { 89 scanf("%d%d",&x,&y); 90 add(x,y); 91 add(y,x); 92 } 93 dfs1(1,0); 94 dfs2(1,1); 95 scanf("%d",&m); 96 for(int i=1;i<n+m;i++) 97 { 98 scanf("%s",ch); 99 if(ch[0]==‘W‘) 100 { 101 scanf("%d",&x); 102 y=1; 103 int ans=0; 104 while(top[x]!=top[y]) 105 { 106 if(dep[top[x]]>dep[top[y]])swap(x,y); 107 ans+=query(1,n,idx[top[y]],idx[y],1); 108 y=fa[top[y]]; 109 } 110 if(dep[x]<dep[y])swap(x,y); 111 ans+=query(1,n,idx[y],idx[x],1); 112 printf("%d\n",ans-1); 113 } 114 else 115 { 116 scanf("%d%d",&x,&y); 117 if(x>y)swap(x,y); 118 if(x==1) 119 { 120 up(1,n,idx[y],idx[y],1); 121 } 122 else if(fa[x]==y) 123 { 124 up(1,n,idx[x],idx[x],1); 125 } 126 else 127 { 128 up(1,n,idx[y],idx[y],1); 129 } 130 } 131 } 132 }
[POI2007]ZAP-Queries
这里:http://www.cnblogs.com/suika/p/8416136.html
[POI2008]PLA-Postering
题意:https://www.luogu.org/problemnew/show/P3467
分析:维护一个单调增的栈,如果当前高度大于栈顶,ans+1;否则弹栈直到栈顶小于等于当前高度。
代码:
1 #include <stdio.h> 2 #include <string.h> 3 #include <algorithm> 4 using namespace std; 5 int st[250050],top,n,ans; 6 int main() 7 { 8 scanf("%d",&n); 9 int x,y; 10 for(int i=1;i<=n;i++) 11 { 12 scanf("%d%d",&y,&x); 13 if(top==0) 14 { 15 ans++; 16 st[top++]=x;continue; 17 } 18 if(x<=st[top-1]) 19 { 20 while(top&&x<st[top-1])top--; 21 if(!top||x>st[top-1])ans++; 22 st[top++]=x; 23 } 24 else 25 { 26 ans++; 27 st[top++]=x; 28 } 29 } 30 printf("%d",ans); 31 }
[POI2005]SKA-Piggy Banks
题意:https://www.luogu.org/problemnew/show/P3420
分析:每个罐子向里面含有的钥匙连边,显然图中不会有复杂的环套环这种,考虑每个联通快,如果是环则对答案贡献为1,否则对答案贡献为入度为0的点的个数。
代码:
1 #include <stdio.h> 2 #include <string.h> 3 #include <algorithm> 4 using namespace std; 5 #define N 1000010 6 int n,fa[N],ans,c[N],f[N]; 7 void read(int &x) 8 { 9 int f=1;x=0;char s=getchar(); 10 while(s<‘0‘||s>‘9‘){if(s==‘-‘)f=-1;s=getchar();} 11 while(s>=‘0‘&&s<=‘9‘){x=(x<<3)+(x<<1)+s-‘0‘;s=getchar();} 12 x*=f; 13 } 14 int find(int x) 15 { 16 return fa[x]^x?fa[x]=find(fa[x]):x; 17 } 18 int main() 19 { 20 read(n); 21 register int i; 22 int x; 23 for(i=1;i<=n;++i)fa[i]=i; 24 for(i=1;i<=n;++i) 25 { 26 read(x); 27 int di=find(i),dx=find(x); 28 c[i]++; 29 fa[di]=dx; 30 } 31 for(i=1;i<=n;++i) 32 { 33 if(fa[i]==i)ans++; 34 } 35 for(i=1;i<=n;++i) 36 { 37 if(!c[i]) 38 { 39 int di=find(i); 40 if(!f[di])f[di]=1; 41 else ans++; 42 } 43 } 44 printf("%d",ans); 45 }
[POI2008]STA-Station
题意:给出一个N个点的树,找出一个点来,以这个点为根的树时,所有点的深度之和最大
分析:树形DP,换根时减去儿子的子树大小加上n-儿子的子树大小。
代码:
1 #include <stdio.h> 2 #include <string.h> 3 #include <algorithm> 4 using namespace std; 5 #define N 1000010 6 #define LL long long 7 int head[N],to[N<<1],nxt[N<<1],cnt,n; 8 int dep[N],fa[N],siz[N],ans; 9 LL sum[N],mx; 10 void read(int &x) 11 { 12 int f=1;x=0;char s=getchar(); 13 while(s<‘0‘||s>‘9‘){if(s==‘-‘)f=-1;s=getchar();} 14 while(s>=‘0‘&&s<=‘9‘){x=(x<<3)+(x<<1)+s-‘0‘;s=getchar();}x*=f; 15 } 16 inline void add(int u,int v) 17 { 18 to[++cnt]=v; 19 nxt[cnt]=head[u]; 20 head[u]=cnt; 21 } 22 void dfs(int x,int y) 23 { 24 siz[x]=1; 25 dep[x]=dep[y]+1; 26 sum[1]+=dep[x]; 27 fa[x]=y; 28 register int i; 29 for(i=head[x];i;i=nxt[i]) 30 { 31 if(to[i]==y)continue; 32 dfs(to[i],x); 33 siz[x]+=siz[to[i]]; 34 } 35 } 36 void niu(int x) 37 { 38 register int i; 39 for(i=head[x];i;i=nxt[i]) 40 { 41 if(to[i]==fa[x])continue; 42 sum[to[i]]=sum[x]-(siz[to[i]]-1)+(n-siz[to[i]]-1); 43 if(sum[to[i]]>mx) 44 { 45 ans=to[i];mx=sum[to[i]]; 46 } 47 else if(sum[to[i]]==mx&&to[i]<ans)ans=to[i]; 48 niu(to[i]); 49 } 50 } 51 int main() 52 { 53 read(n); 54 int x,y; 55 register int i; 56 for(i=1;i<n;++i) 57 { 58 read(x);read(y); 59 add(x,y);add(y,x); 60 } 61 dfs(1,0); 62 ans=1; 63 mx=sum[1]; 64 niu(1); 65 printf("%d",ans); 66 }