hdu5861(Road)
题目链接:传送门
题目大意:有n个点 组成n-1段,每一段开着的时候都有花费Vi,有m组要求,对于每组要求 [x,y]之间可达,对于每一段你有一次开关的机会(最初都是关闭的)
问怎样安排段落得开闭时间使花费最小,输出每天的花费
题目思路:网上题解很多是线段树,但感觉不需要线段树,只需要统计每个点第一次出现的时间(开)和最后一次出现的时间(关)然后以时间为循环扫一遍即可。
于是自己先写了一发,全程用vector模拟,估计是插入和删除操作过多,以及vector本身速度慢,不幸TLE。实际上我模拟的操作也就是想对于每一次
询问,将未覆盖的点(之前还没出现过)标记为已覆盖,加入到相应vector中。而关键在于怎样快速的处理一段点是否被覆盖?
我是用vecotr保存 1~n然后只要当前被覆盖,将覆盖过的点删除,剩下没覆盖的点。而且每次询问的查找是用二分,应该很快了。结果还是Tle
第二种方法(参考网上大牛),用并查集。fp[i]表示 i~第一个未覆盖的点,这样对于询问来说,只需要常数级的操作就能判断更新出来。实在太高明了%%%
附上TLE代码
#include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <algorithm> #include <cstring> #include <stack> #include <cctype> #include <queue> #include <string> #include <vector> #include <set> #include <map> #include <climits> #define lson rt<<1,l,mid #define rson rt<<1|1,mid+1,r #define fi first #define se second #define ping(x,y) ((x-y)*(x-y)) #define mst(x,y) memset(x,y,sizeof(x)) #define mcp(x,y) memcpy(x,y,sizeof(y)) using namespace std; #define gamma 0.5772156649015328606065120 #define MOD 1000000007 #define inf 0x3f3f3f3f #define N 200005 #define maxn 100005 typedef pair<int,int> PII; typedef long long LL; int n,m,k,T; int a[N]; vector<int>V[N],E[N],K,er; struct Node{ int x,y; }node[N]; int ans[N]; int main(){ //freopen("in.txt","r",stdin); int i,j,x,y,v,l; while(scanf("%d%d",&n,&m)!=EOF){ for(i=1;i<n;++i)scanf("%d",&a[i]); K.clear(); for(i=1;i<=n;++i)K.push_back(i); for(i=1;i<=m;++i){ V[i].clear();E[i].clear(); scanf("%d%d",&node[i].x,&node[i].y); if(node[i].x>node[i].y){ node[i].x^=node[i].y^=node[i].x^=node[i].y; } node[i].y--; } vector<int>::iterator it; for(i=1;i<=m;++i){ int pos=lower_bound(K.begin(),K.end(),node[i].x)-K.begin(); it=K.begin()+pos; int cnt=0; while(pos<K.size()&&node[i].y>=K[pos]){ V[i].push_back(K[pos++]); ++cnt; } for(;it!=K.end()&&cnt;--cnt){ K.erase(it); } } K.clear(); for(i=1;i<=n;++i)K.push_back(i); for(i=m;i>=1;--i){ int pos=lower_bound(K.begin(),K.end(),node[i].x)-K.begin(); it=K.begin()+pos; int cnt=0; while(pos<K.size()&&node[i].y>=K[pos]){ E[i].push_back(K[pos++]); ++cnt; } for(;it!=K.end()&&cnt;--cnt) K.erase(it); } int temp=0; for(i=1;i<=m;++i){ for(int &u:V[i]) temp+=a[u]; for(int &u:E[i-1]) temp-=a[u]; printf("%d\n",temp); } } return 0; }
AC代码 1622ms
#include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <algorithm> #include <cstring> #include <stack> #include <cctype> #include <queue> #include <string> #include <vector> #include <set> #include <map> #include <climits> #define lson rt<<1,l,mid #define rson rt<<1|1,mid+1,r #define fi first #define se second #define ping(x,y) ((x-y)*(x-y)) #define mst(x,y) memset(x,y,sizeof(x)) #define mcp(x,y) memcpy(x,y,sizeof(y)) using namespace std; #define gamma 0.5772156649015328606065120 #define MOD 1000000007 #define inf 0x3f3f3f3f #define N 200005 #define maxn 100005 typedef pair<int,int> PII; typedef long long LL; int n,m,k,T; int a[N]; vector<int>V[N],E[N],K,er; struct Node{ int x,y; }node[N]; int ans[N],fp[N]; int findp(int x){return fp[x]==x?x:fp[x]=findp(fp[x]);} int main(){ //freopen("in.txt","r",stdin); int i,j,x,y,v,l; while(scanf("%d%d",&n,&m)!=EOF){ for(i=1;i<n;++i)scanf("%d",&a[i]); for(i=1;i<=m;++i){ V[i].clear();E[i].clear(); scanf("%d%d",&x,&y); if(x>y)x^=y^=x^=y; y--; node[i].x=x;node[i].y=y; } for(i=1;i<=n;++i)fp[i]=i; for(i=1;i<=m;++i){ while(true){ x=findp(node[i].x); y=node[i].y; if(x>y)break; fp[x]=x+1; V[i].push_back(x); } } for(i=1;i<=n;++i)fp[i]=i; for(i=m;i>=1;--i){ while(true){ x=findp(node[i].x); y=node[i].y; if(x>y)break; fp[x]=x+1; E[i].push_back(x); } } int temp=0; for(i=1;i<=m;++i){ for(int &u:V[i])temp+=a[u]; printf("%d\n",temp); for(int &u:E[i])temp-=a[u]; } } return 0; }