T1世界线
这题看着挺那啥的,其实加入我们考虑一下平面向量,那么其实就是可以达到的点的统计;
我们发现一个点能到达的点就是他的儿子们能到达的点的合集,我们可以用bitset来写,那么
可以分成两部分,或者回收一下,就比方说一个点要是被其所有的爸爸搜索过了,那他就没用了,直接删掉这个点就好了
内存限制256MB 恩不错
#include<bits/stdc++.h> using namespace std; inline int read() { int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); } return x*f; } bitset<60001> s[30001]; int n,m,num; int out[60001],in[60001]; int head[60001],nxt[120001],to[120000]; int bh[60001]; long long ans; bool vis[60001]; int ljt[60001],top,tot; void add(int x,int y) { to[++num]=y; nxt[num]=head[x]; head[x]=num; } void sc(int x) { ans+=s[bh[x]].count()-1-out[x]; s[ljt[++top]=bh[x]].reset(); } inline int New() { if(top) return ljt[top--]; else return ++tot; } void dfs(int x) { vis[x]=1; if(!bh[x]) bh[x]=New(); s[bh[x]].set(x); for(int i=head[x];i;i=nxt[i]) { int y=to[i]; if(vis[y]) { s[bh[x]]|=s[bh[y]]; in[y]--; if(in[y]==0) sc(y); continue; } dfs(y); s[bh[x]]|=s[bh[y]]; in[y]--; if(in[y]==0) sc(y); } } int main() { //freopen("a.in","r",stdin); n=read(),m=read(); for(int i=1;i<=m;i++) { int x=read(),y=read(); in[y]++,out[x]++,add(x,y); } for(int i=1;i<=n;i++) { if(!vis[i]) { dfs(i); if(!in[i]) sc(i); } } cout<<ans; }
T2时间机器
恩,很不错的题目。第一眼,好像可以写个dfs骗分,第二眼,好像是个贪心,第三眼,咋贪啊??
想了一会我们发现,最优的策略其实是在所有最小电压小与该节点最小电压的电阻中找最大电压最接近它的
那么,我们可以随手胡一个n方的贪心,那么这很显然是无法拿到所有的分数的
那么我们应该如何进行优化呢???
我们按照最低电压对电阻和节点从大到小进行排序,我们发现我们每次找的那个最大电压接近他的,其实就是他的后继
但要是为了写一个贪心而专门写一颗平衡树的话,不值啊
我会用set!!!
1到n扫一边排完序的结点,每扫一个,将最小电压小于它的全部压入set里,查询后继就好了
那么总体复杂度就是常数大点的nlog(n)两次排序,电阻进出各一次,常数大概是5到4,不过对于这个题,轻轻松松
1 #include<bits/stdc++.h>//多组数据 清空啊 2 using namespace std; 3 inline int read() 4 { 5 int x=0,f=1; 6 char ch=getchar(); 7 while(ch<'0'||ch>'9') 8 { 9 if(ch=='-') 10 f=-1; 11 ch=getchar(); 12 } 13 while(ch>='0'&&ch<='9') 14 { 15 x=(x<<1)+(x<<3)+(ch^48); 16 ch=getchar(); 17 } 18 return x*f; 19 } 20 const int maxn=5e4+1; 21 const int maxm=5e4+1; 22 const int inf=1e9+1; 23 int n,m; 24 struct node{ 25 int l,r,x; 26 }a[maxn],b[maxn],c; 27 struct node1{ 28 int x,id; 29 bool friend operator<(node1 x,node1 y) 30 { 31 return x.x<y.x||(x.x==y.x&&x.id<y.id); 32 } 33 }g; 34 int numr,numa; 35 set<node1> q; 36 bool cmp(node a,node b) 37 { 38 return a.l<b.l; 39 } 40 int main() 41 { 42 //freopen("a.in","r",stdin); 43 int t=read(); 44 while(t--) 45 { 46 for(int i=1;i<=max(n,m);i++) 47 a[i]=b[i]=c; 48 n=read(),m=read(); 49 int l=0; 50 for(int i=1;i<=n;i++) 51 a[i].l=read(),a[i].r=read(),a[i].x=read(); 52 for(int i=1;i<=m;i++) 53 b[i].l=read(),b[i].r=read(),b[i].x=read(); 54 sort(a+1,a+n+1,cmp); 55 sort(b+1,b+m+1,cmp); 56 int flag=0,j=1; 57 g.id=0; g.x=inf;q.insert(g); 58 for(int i=1;i<=n;i++) 59 { 60 while(b[j].l<=a[i].l&&j<=m) 61 g.id=j++,g.x=b[g.id].r,q.insert(g); 62 g.id=0,g.x=a[i].r; 63 while(a[i].x) 64 { 65 g=*q.lower_bound(g);//跟彭丙童学的set找后继,主要是没时间了,没有时间打平衡树了,直接用stl水吧!!!!!!!!!!!!!!!!!! 66 if(g.x==inf) 67 break; 68 int t=min(b[g.id].x,a[i].x); 69 b[g.id].x-=t,a[i].x-=t; 70 if(!b[g.id].x) q.erase(g); 71 } 72 if(a[i].x) 73 { 74 flag=1; 75 break; 76 } 77 } 78 if(flag==1) 79 { 80 puts("No"); 81 } 82 else 83 { 84 puts("Yes"); 85 } 86 q.clear(); 87 } 88 }
T3weight
首先建立一颗最小生成树;
对于每个树上的边,我们找的是链接这两点的所有简单路径里最短的边-1;
对于非树边,我们找的是这俩点在最小生成树路径上的最大边-1;
这玩意树剖一下实现就好了
#include<bits/stdc++.h> #define debug exit(0); #define jb cout<<"jb"; #define lid id<<1 #define rid id<<1|1 using namespace std; inline int read() { int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); } return x*f; } const int maxn=1e5; struct qxx{ int from,to,w,id; }g[maxn]; bool cmp(qxx x,qxx y){ return x.w<y.w; } int ans[maxn]; int die[maxn]; int val[maxn]; int a[maxn],xjb; bool vis[maxn]; int n,m,q,top[maxn],num,fa[maxn],size[maxn],tot=1,cnt,dfn[maxn],son[maxn],head[maxn*3],col[maxn],dep[maxn],nu[maxn]; struct edge{ int to,nxt,v; }e[maxn*3]; struct tree{ int l,r,max,min,lazy; }tr[maxn<<2]; inline int getfa(int x) { if(die[x]!=x) die[x]=getfa(die[x]); return die[x]; } inline void add(int x,int y,int z) { e[++num].to=y; e[num].nxt=head[x]; e[num].v=z; head[x]=num; } void krus() { for(int i=1;i<=n;i++) die[i]=i; sort(g+1,g+1+m,cmp); for(int i=1;i<=m;i++) { int a=g[i].from,b=g[i].to; if(getfa(a)!=getfa(b)) { die[getfa(a)]=getfa(b); vis[g[i].id]=1; add(a,b,g[i].w); add(b,a,g[i].w); } } } void pushdown(int id) { if(tr[id].lazy==0x7fffffff) return ; tr[lid].lazy=min(tr[id].lazy,tr[lid].lazy); tr[rid].lazy=min(tr[rid].lazy,tr[id].lazy); tr[lid].min=min(tr[lid].min,tr[id].lazy); tr[rid].min=min(tr[rid].min,tr[id].lazy); tr[id].lazy=0x7fffffff; } void pushup(int id) { tr[id].max=max(tr[lid].max,tr[rid].max); } void build(int id,int l,int r) { tr[id].l=l,tr[id].r=r; tr[id].lazy=0x7fffffff; tr[id].min=0x7fffffff; if(l==r) { tr[id].max=a[l]; return ; } int mid=(tr[id].l+tr[id].r)>>1; build(lid,l,mid); build(rid,mid+1,r); pushup(id); } inline int querym(int id,int l,int r) { if(tr[id].l>=l&&tr[id].r<=r) return tr[id].max; pushdown(id); int mid=(tr[id].l+tr[id].r)>>1,ans=0; if(l<=mid)ans=max(ans,querym(lid,l,r)); if(r>mid) ans=max(ans,querym(rid,l,r)); return ans; } inline int queryn(int id,int pos) { if(tr[id].l==tr[id].r) return tr[id].min; pushdown(id); int mid=(tr[id].l+tr[id].r)>>1; if(pos<=mid)return queryn(lid,pos); if(pos>mid)return queryn(rid,pos); } void update(int id,int l,int r,int val) { if(tr[id].l>=l&&tr[id].r<=r) { tr[id].lazy=min(tr[id].lazy,val); tr[id].min=min(tr[id].min,val); return ; } int mid=(tr[id].l+tr[id].r)>>1; pushdown(id); if(l<=mid) update(lid,l,r,val); if(r>mid) update(rid,l,r,val); } inline int treemax(int x,int y,int val) { int ans=0; while(top[x]!=top[y]) { if(dep[top[x]]<dep[top[y]]) swap(x,y); ans=max(ans,querym(1,dfn[top[x]],dfn[x])); update(1,dfn[top[x]],dfn[x],val-1); x=fa[top[x]]; } if(dep[x]>dep[y]) swap(x,y); ans=max(ans,querym(1,dfn[x]+1,dfn[y])); update(1,dfn[x]+1,dfn[y],val-1); return ans; } void dfs1(int x,int deep) { dep[x]=deep+1; size[x]=1; for(int i=head[x];i;i=e[i].nxt) { int y=e[i].to; if(!dep[y]) { fa[y]=x; val[y]=e[i].v; dfs1(y,deep+1); size[x]+=size[y]; if(size[son[x]]<size[y]) son[x]=y; } } } void dfs2(int x,int ff) { top[x]=ff; dfn[x]=++cnt; a[cnt]=val[x]; if(!son[x]) return ; dfs2(son[x],ff); for(int i=head[x];i;i=e[i].nxt) { int y=e[i].to; if(y!=fa[x]&&y!=son[x]) { dfs2(y,y); } } } int main() { //freopen("weight1.in","r",stdin); //freopen("out","w",stdout); n=read(),m=read(),xjb=read(); for(int i=1;i<=m;i++) g[i].from=read(),g[i].to=read(),g[i].w=read(),g[i].id=i; krus(); dfs1(1,0); dfs2(1,1); build(1,1,n); for(int i=1;i<=m;i++) { if(!vis[g[i].id]) { if(getfa(g[i].from)!=getfa(1)) { ans[g[i].id]=0; continue; } else { ans[g[i].id]=treemax(g[i].from,g[i].to,g[i].w)-1; continue; } } } for(int i=1;i<=m;i++) { if(vis[g[i].id]) { if(getfa(g[i].from)!=getfa(1)) { ans[g[i].id]=0; continue; } int a=g[i].from,b=g[i].to; if(dep[a]>dep[b]) ans[g[i].id]=queryn(1,dfn[a]); else ans[g[i].id]=queryn(1,dfn[b]); } } for(int i=1;i<=m;i++) { if(ans[i]==0x7fffffff) printf("-1 "); else printf("%d ",ans[i]); } }