标签:com chmod 输入输出 区间修改 swap target ever and ret
Time Limit: 10000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
http://acm.hdu.edu.cn/showproblem.php?pid=3966
#include<cstdio> #include<cstring> #include<iostream> #define N 50001 using namespace std; int n,m,p; class work { private: int a[N],head[N],edge_tot,tree_cnt; int son[N],dep[N],sz,bl[N],id[N],f[N]; struct edge{int to,next;}e[N*2]; struct node{int l,r,f,sum;}tr[N*2]; public: inline int read() { int x=0,f=1;char c=getchar(); while(c<‘0‘||c>‘9‘) {if(c==‘-‘) f=-1;c=getchar();} while(c>=‘0‘&&c<=‘9‘) {x=x*10+c-‘0‘;c=getchar();} return x*f; } inline void add(int u,int v)//加边 { e[++edge_tot].to=v;e[edge_tot].next=head[u];head[u]=edge_tot; e[++edge_tot].to=u;e[edge_tot].next=head[v];head[v]=edge_tot; } inline void point_change(int k,int x,int y)//单点修改 { if(tr[k].l==tr[k].r) {tr[k].sum=y;return;} int mid=tr[k].l+tr[k].r>>1,l=k+1,r=k+(tr[k+1].r-tr[k+1].l+1<<1); if(x<=mid) point_change(l,x,y); else point_change(r,x,y); tr[k].sum=tr[l].sum+tr[r].sum; } inline void build(int l,int r) { tree_cnt++; tr[tree_cnt].l=l;tr[tree_cnt].r=r; if(l==r) return; int mid=l+r>>1; build(l,mid);build(mid+1,r); } void init() { build(1,n); for(int i=1;i<=n;i++) a[i]=read(); int u,v; for(int i=1;i<=m;i++) { u=read();v=read(); add(u,v); } } inline void dfs1(int x,int fa)//树链剖分2次dfs { son[x]++; for(int i=head[x];i;i=e[i].next) { if(e[i].to==fa) continue; dep[e[i].to]=dep[x]+1; f[e[i].to]=x; dfs1(e[i].to,x); son[x]+=son[e[i].to]; } } inline void dfs2(int x,int chain) { sz++; id[x]=sz; bl[x]=chain; int m=0; for(int i=head[x];i;i=e[i].next) { if(dep[e[i].to]<dep[x]) continue; if(son[e[i].to]>son[m]) m=e[i].to; } if(!m) return; dfs2(m,chain); for(int i=head[x];i;i=e[i].next) { if(e[i].to==m||dep[e[i].to]<dep[x]) continue; dfs2(e[i].to,e[i].to); } } inline void down(int k)//标记下传 { int l=k+1,r=k+(tr[k+1].r-tr[k+1].l+1<<1); tr[l].sum+=(tr[l].r-tr[l].l+1)*tr[k].f; tr[l].f+=tr[k].f; tr[r].sum+=(tr[r].r-tr[r].l+1)*tr[k].f; tr[r].f+=tr[k].f; tr[k].f=0; } inline void query_change(int k,int opl,int opr,int w)//区间修改 { if(tr[k].l>=opl&&tr[k].r<=opr) { tr[k].sum+=(tr[k].r-tr[k].l+1)*w; tr[k].f+=w; return; } if(tr[k].f&&tr[k].l!=tr[k].r) down(k); int mid=tr[k].l+tr[k].r>>1,l=k+1,r=k+(tr[k+1].r-tr[k+1].l+1<<1); if(opl<=mid) query_change(l,opl,opr,w); if(opr>mid) query_change(r,opl,opr,w); tr[k].sum=tr[l].sum+tr[r].sum; } inline void solve_q_change(int u,int v,int w) { while(bl[u]!=bl[v]) { if(dep[bl[u]]<dep[bl[v]]) swap(u,v); query_change(1,id[bl[u]],id[u],w); u=f[bl[u]]; } if(id[u]>id[v]) swap(u,v); query_change(1,id[u],id[v],w); } inline void solve_p_query(int k,int x)//区间查询 { if(tr[k].l==tr[k].r) {printf("%d\n",tr[k].sum);return;} if(tr[k].f&&tr[k].l!=tr[k].r) down(k); int mid=tr[k].l+tr[k].r>>1,l=k+1,r=k+(tr[k+1].r-tr[k+1].l+1<<1); if(x<=mid) solve_p_query(l,x); else solve_p_query(r,x); } void solve() { for(int i=1;i<=n;i++) point_change(1,id[i],a[i]); int u,v,k;char c; for(int i=1;i<=p;i++) { cin>>c; switch(c) { case ‘I‘:u=read();v=read();k=read();solve_q_change(u,v,k);break; case ‘D‘:u=read();v=read();k=read();solve_q_change(u,v,-k);break; case ‘Q‘:u=read();solve_p_query(1,id[u]);break; } } } inline void pre() { memset(head,0,sizeof(head)); memset(son,0,sizeof(son)); memset(dep,0,sizeof(dep)); memset(tr,0,sizeof(tr)); edge_tot=tree_cnt=sz=0; } void start() { pre(); init(); dfs1(1,0); dfs2(1,1); solve(); } }o; int main() { while(scanf("%d%d%d",&n,&m,&p)!=EOF) o.start(); return 0; }
3个错误
1、Multiple test cases, process to the end of input.多组数据输入
不看清楚输入输出,一周内第三次犯此错误
2、sz变量未清零
3、在输入点权时,同时执行修改操作,错。
因为线段树是根据时间戳建立的,所以要在dfs完,确定完id[]后在修改
标签:com chmod 输入输出 区间修改 swap target ever and ret
原文地址:http://www.cnblogs.com/TheRoadToTheGold/p/6390851.html