我哭啊……这题在考试的时候(我不是山东的,CH大法吼)没想出来……只写了50分的暴力QAQ

  而且苦逼的写的比正解还长……我骗点分容易吗QAQ

  骗分做法:

  1.$n,m\leq 1000$: 直接找一个关键点做根进行深搜,算出其他关键点都与root连通的最小边权和,再×2

  2.一条链的情况:用set维护序列中哪些点选了,然后ans=(sum[tail]-sum[head])*2; 其中sum[i]表示从序列首到第 i 个的边长之和……嗯就是前缀和优化一下= =取首和尾这一段的Len之和

  3.保证第一次一定变动1号村庄,且以后1不再变动:以1为根,每次update(x),将从x到1的所有边更新一遍,看有多少个点需要经过它,如果是新加的边就在ans中加进来,如果这次删点后这条边无用了,就在ans中减去

  以上就是50分的骗分做法……写起来倒是不难(正解写起来更简单QAQ)

  1 //Huce #4 B
  2 #include<set>
  3 #include<vector>
  4 #include<cstdio>
  5 #include<cstdlib>
  6 #include<cstring>
  7 #include<iostream>
  8 #include<algorithm>
  9 #define rep(i,n) for(int i=0;i<n;++i)
 10 #define F(i,j,n) for(int i=j;i<=n;++i)
 11 #define D(i,j,n) for(int i=j;i>=n;--i)
 12 using namespace std;
 13 
 14 int getint(){
 15     int v=0,sign=1; char ch=getchar();
 16     while(ch<'0'||ch>'9') {if (ch=='-') sign=-1; ch=getchar();}
 17     while(ch>='0'&&ch<='9') {v=v*10+ch-'0'; ch=getchar();}
 18     return v*sign;
 19 }
 20 typedef long long LL;
 21 const int N=100010,INF=~0u>>2;
 22 /*******************tamplate********************/
 23 int head[N],to[N<<1],next[N<<1],len[N<<1],cnt;
 24 void add(int x,int y,int z){
 25     to[++cnt]=y; next[cnt]=head[x]; len[cnt]=z; head[x]=cnt;
 26     to[++cnt]=x; next[cnt]=head[y]; len[cnt]=z; head[y]=cnt;
 27 }
 28 /*********************edge**********************/
 29 int n,m,du[N];
 30 bool sign[N],vis[N];
 31 
 32 namespace work1{
 33     LL ans;
 34     bool dfs(int x){
 35         bool tmp=sign[x];
 36         vis[x]=1;
 37         for(int i=head[x];i;i=next[i]) if(!vis[to[i]]){
 38             if (dfs(to[i])){
 39                 ans+=len[i];
 40                 tmp=1;
 41             }
 42         }
 43         return tmp;
 44     }
 45     LL solve(){
 46         ans=0;
 47         memset(vis,0,sizeof vis);
 48         F(i,1,n) if (sign[i]){
 49             dfs(i);
 50             return ans;
 51         }
 52     }
 53     void work1(){
 54         int x;
 55         F(i,1,m){
 56             x=getint(); sign[x]^=1;
 57             printf("%lld\n",solve()*2);
 58         }
 59     }
 60 }
 61 namespace work2{
 62     int a[N],tot,num[N];
 63     LL sum[N];
 64     void dfs(int x,int l){
 65         vis[x]=1;
 66         a[++tot]=x;
 67         sum[tot]=sum[tot-1]+l;
 68         num[x]=tot;
 69         for(int i=head[x];i;i=next[i])
 70             if (!vis[to[i]])
 71                 dfs(to[i],len[i]);
 72     }
 73     set<int>s;
 74     set<int>::iterator it;
 75     void work2(){
 76         F(i,1,n) if (du[i]==1){
 77             dfs(i,0);
 78             break;
 79         }
 80 //        F(i,1,tot) printf("%d ",a[i]);puts("");
 81         int x;
 82         F(i,1,m){
 83             x=getint();
 84             sign[x]^=1;
 85             if (sign[x]) s.insert(num[x]);
 86             else{
 87                 it=s.find(num[x]);
 88                 s.erase(it);
 89             }
 90             it=s.end(); it--;
 91 //            printf("%d %d\n",*s.begin(),*s.rbegin());
 92             printf("%lld\n",(sum[*s.rbegin()]-sum[*s.begin()])*2);
 93         }
 94     }
 95 }
 96 namespace work3{
 97     int fa[N],num[N],dis[N];
 98     LL ans;
 99     bool vis[N];
100     void dfs(int x){
101         vis[x]=1;
102         for(int i=head[x];i;i=next[i])
103             if (!vis[to[i]]){
104                 fa[to[i]]=x;
105                 dis[to[i]]=len[i];
106                 dfs(to[i]);
107             }
108     }
109     void update(int x,int v){
110         if (x==1) return;
111         if (v==1){
112             num[x]++;
113             if (num[x]==1) ans+=dis[x];
114         }else{
115             num[x]--;
116             if (num[x]==0) ans-=dis[x];
117         }
118         update(fa[x],v);
119     }
120     void work3(){
121         int x;
122         memset(vis,0,sizeof vis);
123         dfs(1);
124 //        F(i,1,n) printf("%d ",dis[i]); puts("");
125         F(i,1,m){
126             x=getint(); sign[x]^=1;
127             update(x,sign[x]?1:-1);
128             printf("%lld\n",ans*2);
129         }
130     }
131 }
132 int main(){
133 #ifndef ONLINE_JUDGE
134     freopen("B.in","r",stdin);
135 //    freopen("output.txt","w",stdout);
136 #endif
137     n=getint(); m=getint();
138     int x,y,z,mx=0;
139     F(i,2,n){
140         x=getint(); y=getint(); z=getint();
141         add(x,y,z);
142         du[x]++; du[y]++;
143         mx=max(mx,max(du[x],du[y]));
144     }
145     if (n<=1000) work1::work1();
146     else if (mx==2)    work2::work2();
147     else 
148         work3::work3();
149     return 0;
150 }
50分暴力

相关文章: