首先说一下hdu的题意是输出每一个点的子树中比他小的点的个数。
poj的题意是输出子树的节点数,这基本就算是一个题了。
本来是不断地dfs就好了,但是这个栈的内存会爆,学长说了,C++不是可以手动扩栈吗,
然后就加上这一句#pragma comment(linker, "/STACK:102400000,102400000")
但是我问他区域赛可以吗,他说只要你不写错,一般不会的,还有一种什么模拟栈,然后就花了一天学了一下,就是不断的入栈和出栈,
然后加上一个树状数组各种搞
因为之前树状数组只是简单的运用一下,也不是很摸得透。今天顺带复习了一下,感觉还是蛮好的。
代码如下:
#include <cstdio>
#include <cstring>
#include <stack>
using namespace std;
#define maxx 100010
int head[maxx*2],par[2*maxx];
int l[maxx],r[maxx];
int ans[maxx];
int vis[maxx];
int cnt,toa;
int n,m;
stack <int >ss;
struct node {
int s,next;
}edge[maxx*2];
void add(int x,int y){
edge[toa].s=x;edge[toa].next=head[y];head[y]=toa++;
}
int lowbit (int x){
return x&-x;
}
int sum(int x){
int r=0;
while(x>0){
r+=par[x];
x-=lowbit(x);
}
return r;
}
void update(int x,int a){
while(x<2*maxx){
par[x]+=a;
x+=lowbit(x);
}
}
void dfs(int root){
cnt=1;
while(!ss.empty())
ss.pop();
memset(vis,0,sizeof(vis));
ss.push(root);
while(!ss.empty()){
int u=ss.top();
if(!vis[u]){
l[u]=cnt++;
vis[u]=1;
}
int flag=0;
for(int i=head[u];i!=-1;i=edge[i].next){
if(!vis[edge[i].s]){
flag=1;
head[u]=edge[i].next;//把u的next标记到当前节点,在调用的时候就可以跳过这一个了,本来以为这个可以优化好多时间的,谁知道只快了10ms。。。。
ss.push(edge[i].s);
break;
}
}
if(flag) continue;
if(vis[u]){
r[u]=cnt++;
ss.pop();
}
}
}
void slove (){
for(int i=1;i<=n;i++){
ans[i]=sum(r[i]-1)-sum(l[i]);//看不懂自己把r[i],l[i]打印出来好好研究一下,
update(l[i],1);
}
}
int main(){
while(scanf("%d%d",&n,&m)&&(n||m)){
memset(head,-1,sizeof(head));
memset(par,0,sizeof(par));
toa=0;
int a,b;
for(int i=0;i<n-1;i++){
scanf("%d%d",&a,&b);
add(a,b);//建立邻接表
add(b,a);
}
dfs(m);
slove();
for(int i=1;i<n;i++)
printf("%d ",ans[i]);
printf("%d\n",ans[n]);
}
}
poj apple tree
这个题的坑就是我看题一直以为只删点,wa了几发,才看到摘或长出来,摘了就长出来,长出来就摘。
即用一个数组标记他是否被摘,如果被摘,那么就+1
else -1;
#include <cstdio>
#include <cstring>
#include <stack>
using namespace std;
#define maxx 100010
int head[maxx*2],par[2*maxx];
int l[maxx],r[maxx];
int ans[maxx];
int vis[maxx];
int vis1[maxx];
int cnt,toa;
int n,m;
stack <int >ss;
struct node {
int s,next;
}edge[maxx*2];
void add(int x,int y){
edge[toa].s=x;edge[toa].next=head[y];head[y]=toa++;
}
int lowbit (int x){
return x&-x;
}
int sum(int x){
int r=0;
while(x>0){
r+=par[x];
x-=lowbit(x);
}
return r;
}
void update(int x,int a){
while(x<2*maxx){
par[x]+=a;
x+=lowbit(x);
}
}
void dfs(int root){
cnt=1;
while(!ss.empty())
ss.pop();
memset(vis,0,sizeof(vis));
ss.push(root);
while(!ss.empty()){
int u=ss.top();
if(!vis[u]){
l[u]=cnt++;
vis[u]=1;
}
int flag=0;
for(int i=head[u];i!=-1;i=edge[i].next){
if(!vis[edge[i].s]){
flag=1;
head[u]=edge[i].next;
ss.push(edge[i].s);
break;
}
}
if(flag) continue;
if(vis[u]){
r[u]=cnt++;
ss.pop();
}
}
}
int main(){
while(scanf("%d",&n)!=EOF){
memset(head,-1,sizeof(head));
memset(par,0,sizeof(par));
memset(vis,0,sizeof(vis));
toa=0;
int a,b;
for(int i=0;i<n-1;i++){
scanf("%d%d",&a,&b);
add(a,b);
add(b,a);
}
dfs(1);
for(int i=1;i<=n;i++){
update(r[i],1);
}
int T;
scanf("%d",&T);
while(T--){
char op[2];
scanf("%s",op);
if(op[0]=='C'){
scanf("%d",&a);
if(!vis1[a]){
update(r[a],-1);
vis1[a]=1;
}
else {
update(r[a],1);
vis1[a]=0;
}
}
else
{
scanf("%d",&b);
printf("%d\n",sum(r[b])-sum(l[b]));
}
}
}
}