hdu 4467( 轻重点维护)

写了7000b代码 真是醉了
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cctype>
#include <complex>
#include <cstring>
#include <iomanip>
#include <list>
#include <map>
#include <queue>
#include <stack>
#include <string>
#include <vector>
using namespace std;
#define rep(i, n) for(int i=0; i<n; i++)
#define fab(i, a, b) for(int i=(a); i<=(b); i++)
#define PB push_back
#define MP make_pair
#define LL long long
#define sf scanf
#define pf printf
const int N = 110000;
int n,m;
int head[N],next[N*2],to[N*2];
LL WW[N*2];
int headW[N],nextW[N*2],toW[N*2];
LL W[N*2];
int used[N*2],col[N],d[N],isweight[N];
LL weight[N][2];
int e=0,eW;
LL light0_0,light0_1,light1_1;
LL weight0_0,weight0_1,weight1_1;
vector<int>cal;
int ecnt;
void bug();
struct Edge{
    int u,v;
    LL w;
    Edge(int u=0,int v=0,LL w=0):u(u),v(v),w(w){}
    bool operator<(const Edge& rhs)const{
        if(u!=rhs.u)return u<rhs.u;
        else if(v!=rhs.v)return v<rhs.v;
        else return w<rhs.w;
    }
}E[N*2];
void init(){
    cal.clear();
    e=eW=ecnt=0;
    light1_1=light0_0=light0_1=0;
    weight0_0=weight0_1=weight1_1=0;
   memset(used,0,sizeof used);
   memset(headW,-1,sizeof headW);
   memset(head,-1,sizeof head);
   memset(weight,0,sizeof weight);
   memset(d,0,sizeof d);
   memset(col,0,sizeof col);
   memset(isweight,0,sizeof isweight);
}
void addedge(int u,int v,LL w){
    d[v]++;
    to[e]=v;
    W[e]=w;
    next[e]=head[u];
    head[u]=e++;
}
void addedgeW(int u,int v,LL w){
    toW[eW]=v;
    WW[eW]=w;
    nextW[eW]=headW[u];
    headW[u]=eW++;
}
void input(){
   fab(i,1,n)sf("%d",&col[i]);
   rep(i,m){
       used[i]=0;
       int u,v;
       LL w;
       sf("%d%d%I64d",&u,&v,&w);
       if(u>v)swap(u,v);
       E[i].u=u;E[i].v=v;E[i].w=w;
       //addedge(u,v,w);
       //addedge(v,u,w);
   }
    sort(E,E+m);
    ecnt=0;
    for(int i=1;i<m;i++){
        if(E[i].u==E[ecnt].u&&E[i].v==E[ecnt].v)E[ecnt].w+=E[i].w;
        else{
            ecnt++;
            E[ecnt].u=E[i].u;
            E[ecnt].v=E[i].v;
            E[ecnt].w=E[i].w;
        }
    }
    for(int i=0;i<=ecnt;i++){
        addedge(E[i].u,E[i].v,E[i].w);
        addedge(E[i].v,E[i].u,E[i].w);
    }
}
void predo(){
    int mid=sqrt(n+0.5);
    fab(i,1,n){
        if(d[i]>mid){
            isweight[i]=1;
            cal.PB(i);
        }else{
            isweight[i]=0;
        }
    }
    fab(u,1,n){
        if(isweight[u]){
             for(int p=head[u];~p;p=next[p]){
                 int v=to[p];
                 if(isweight[v]&&v<u){
                     addedgeW(u,v,W[p]);
                     continue;
                 }
                 LL w=W[p];
                 weight[u][col[v]]+=w;
                 if(col[u]!=col[v])weight0_1+=w;
                 else{
                     if(col[u])weight1_1+=w;
                     else weight0_0+=w;
                 }
             }
        }else{
             for(int p=head[u];~p;p=next[p]){
                 int v=to[p];
                 if(isweight[v]||v<u)continue;
                 LL w=W[p];
                 if(col[v]!=col[u]){
                     light0_1+=w;
                 }else{
                     if(col[u])light1_1+=w;
                     else light0_0+=w;
                 }
             }
        }
    }
}
void Change(int x){
    if(isweight[x]){
        if(col[x]){
            weight0_1-=weight[x][0];
            weight1_1-=weight[x][1];
            weight0_1+=weight[x][1];
            weight0_0+=weight[x][0];
        }else{
            weight0_1-=weight[x][1];
            weight0_0-=weight[x][0];
            weight1_1+=weight[x][1];
            weight0_1+=weight[x][0];
        }
        for(int p=headW[x];~p;p=nextW[p]){
            int v=toW[p];
            LL w=WW[p];
            weight[v][col[x]]-=w;
            weight[v][col[x]^1]+=w;
            if(col[v]!=col[x]){
                weight0_1-=w;
                if(col[x]==0)weight1_1+=w;
                else weight0_0+=w;
            }else{
                if(col[x])weight1_1-=w;
                else weight0_0-=w;
                weight0_1+=w;
            }
        }
    }else{
        for(int p=head[x];~p;p=next[p]){
            int v=to[p];
            LL w=W[p];
            if(isweight[v]){
                 weight[v][col[x]]-=w;
                 weight[v][col[x]^1]+=w;
                 int a=col[v],b=col[x];
                 if(a!=b){
                     weight0_1-=w;
                     if(b)weight0_0+=w;
                     else weight1_1+=w;
                 }else{
                     if(a)weight1_1-=w;
                     else weight0_0-=w;
                     weight0_1+=w;
                 }
            }else{
                 if(col[x]!=col[v]){
                    light0_1-=w;
                    if(col[x])light0_0+=w;
                    else light1_1+=w;
                 }
                 else {
                     if(col[x]==0){
                        light0_0-=w;
                     }else {
                         light1_1-=w;
                     }
                     light0_1+=w;
                 }
            }
        }
    }
    col[x]^=1;
}
void Asksum(int a,int b){
    LL ans=0;

    if(a!=b){
        ans=light0_1+weight0_1;
    }else{
        if(a)ans=light1_1+weight1_1;
      else ans=light0_0+weight0_0;                                                                                               }
/*
    if(a!=b)ans=light0_1;
    else if(a)ans=light1_1+weight1_1;
    else ans=light0_0+weight0_0;
    rep(i,cal.size()){
        int u=cal[i];
        if(a==0&&b==0){
            if(col[u]==0)ans+=weight[u][0];
        }else if((a==0&&b==1)||(a==1&&b==0)){
            ans+=weight[u][col[u]^1];
        }else if(a==1&&b==1){
            if(col[u])ans+=weight[u][1];
        }
    }*/
    pf("%I64d\n",ans);
}
void solve(){
     int Q;
     sf("%d",&Q);
     char op[20];
     int a,b;
     while(Q--){
        // bug();
        sf("%s",op);
        if(op[0]==‘A‘){
            sf("%d%d",&a,&b);
            Asksum(a,b);
        }else if(op[0]==‘C‘){
            sf("%d",&a);
            Change(a);
        }
     }
}
void bug(){
    puts("bug");
    /*fab(i,1,n){
        pf("is i = %d  weight %d\n",i,isweight[i]);
    }*/
    pf("light 0_0 = %I64d  0_1 = %I64d  1_1 = %I64d\n",light0_0,light0_1,light1_1);
    pf("weight 0_0 = %I64d  0_1 = %I64d  1_1 = %I64d\n",weight0_0,weight0_1,weight1_1);
    fab(i,1,n){
        if(isweight[i]){
            pf(" wieght i= %d:\n",i);
            pf(" --0 = %I64d    |  ---1 = %I64d \n",weight[i][0],weight[i][1]);
        }
    }
    /*
    fab(i,1,n){
        pf("i = %d :\n",i);
        for(int p=headW[i];~p;p=nextW[p])pf("%d ",to[p]);puts("");
    }*/
}
int main() {
    //freopen("in","r",stdin);
    //freopen("mywa","w",stdout);
    int cas=1;
    while(~sf("%d%d",&n,&m)){
        pf("Case %d:\n",cas++);
        init();
        input();
        predo();
       // bug();
        solve();
    }
    return 0;
}
时间: 2024-12-25 08:47:41

hdu 4467( 轻重点维护)的相关文章

HDU 4467 分块

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4467 题意:给定n个点m条边的无向图,点被染色(黑0/白1),边带边权.然后q个询问.询问分为两种: Change u:把点u的颜色反转(黑变白,白变黑),Asksum a b(a,b的值为0/1):统计所以边的权值和,边的两个点满足一个点的颜色为a,一个点的颜色为b. 思路:考虑暴力的做法.修改可以做法O(1),但是查询就得O(m).所以总复杂度为O(m*q)会TLE.然后考虑图分块.参考HDU

HDU 4467 Graph

Graph Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2618    Accepted Submission(s): 425 Problem DescriptionP. T. Tigris is a student currently studying graph theory. One day, when he was stud

HDU 5033 (单调栈维护凸包) Building

题意: 一个人在x轴上,他的左右两侧都有高楼,给出楼的横坐标Xi和高度Hi还有人的位置pos,求人所能看到的天空的最大角度. 分析: 将建筑物和人的位置从左到右排序,对于每个位置利用栈求一次人左边建筑物的凸包,找到一个最小的角度,然后对称一下,再找一个右边的建筑物的最小角度,两个角度加起来就是答案. 将人左边的建筑物从左到右扫描,下面两种情况会出栈: 栈顶元素楼高小于等于当前扫描到的楼高,因此这是一个单调的栈 栈顶两个楼顶所在直线的斜率 小于 栈顶的楼顶和当前楼顶所在直线的斜率(这里的斜率指的是

hdu 5385 The path(最短路+构造)

题目链接:hdu 5385 The path 维护一个l,r,l从2开始递增,r从N开始递减,每个距离值l,r至多走一步,并且每次将可以到达的点标记,注意最后最大值只能有一个. #include <cstdio> #include <cstring> #include <vector> #include <queue> #include <algorithm> using namespace std; typedef pair<int,in

Kuangbin 带你飞-线段树专题 题解

HDU 1166 敌兵布阵 单调更新区间查询和 #include <map> #include <set> #include <list> #include <cmath> #include <ctime> #include <deque> #include <stack> #include <queue> #include <cctype> #include <cstdio> #inc

图的分块

例1. hdu 4858 项目管理 按点的度数划分为重点(deg>=sqrt(m))和轻点(deg<sqrt(m)), 轻点暴力更新, 重点只更新邻接的重点 #include <iostream> #include <algorithm> #include <math.h> #include <cstdio> #include <vector> #define pb push_back #define REP(i,a,n) for(i

HDU 5869 Different GCD Subarray Query (GCD种类预处理+树状数组维护)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5869 问你l~r之间的连续序列的gcd种类. 首先固定右端点,预处理gcd不同尽量靠右的位置(此时gcd种类不超过loga[i]种). 预处理gcd如下代码,感觉真的有点巧妙... 1 for(int i = 1; i <= n; ++i) { 2 int x = a[i], y = i; 3 for(int j = 0; j < ans[i - 1].size(); ++j) { 4 int g

HDU 4521 小明系列问题——小明序列 (线段树维护DP)

题目地址:HDU 4521 基本思路是DP.找前面数的最大值时能够用线段树来维护节省时间. 因为间隔要大于d. 所以能够用一个队列来延迟更新,来保证每次询问到的都是d个之前的. 代码例如以下: #include <iostream> #include <cstdio> #include <string> #include <cstring> #include <stdlib.h> #include <math.h> #include

HDU 4923 Room and Moor(推理+栈维护)

HDU 4924 Room and Moor 题目链接 题意:给定一个01组成的a序列,要求一个b序列,b序列每个数值为[0, 1]之间的数,并且b序列为非递减序列,要求∑(ai?bi)2最小,求这个最小值 思路:推理,很容易看出,开头一段的0和末尾一段的1等于没有,然后中间每段类似111000这样1在前,0在后的序列,都可以列出一个公式,很容易推出选择的x为共同的一个值,为1的个数/(1的个数+0的个数)a,那么问题就变成要维护一个递增的x,利用一个栈去做维护,如果遇到一个位置递减了,那么就把