2021.10.9
T1:a
Problem:
小 A 有一列数字,这列数字很乱,他看着很不爽。于是他打算删掉其中的一些,使得剩下的序列满足第𝑖个位置的值是𝑖的位置尽可能多。请你告诉他最多能有多少个位置满足。
Solution:
三维偏序
Code:
1 #include<bits/stdc++.h> 2 using namespace std; 3 int n,tot,mx,c[200005]; 4 struct node{ 5 int i,a; 6 }a[100005]; 7 bool cmp(const node &a,const node &b){ 8 if(a.i==b.i) return a.a<b.a; 9 else return a.i<b.i; 10 } 11 inline int lowbit(int x){ 12 return x&-x; 13 } 14 inline void update(int x,int g){ 15 while(x<=mx){ 16 c[x]=max(c[x],g); 17 x+=lowbit(x); 18 } 19 } 20 inline int ask(int x){ 21 int ans=0; 22 while(x){ 23 ans=max(ans,c[x]); 24 x-=lowbit(x); 25 } 26 return ans; 27 } 28 int main(){ 29 scanf("%d",&n); 30 for(int i=1;i<=n;i++){ 31 int x; 32 scanf("%d",&x); 33 if(i<x) continue; 34 tot++; 35 a[tot].i=i-x; 36 a[tot].a=x; 37 mx=max(mx,x); 38 } 39 sort(a+1,a+1+tot,cmp); 40 mx=min(mx,2*n); 41 int ans=0; 42 for(int i=1;i<=tot;i++){ 43 int d=ask(a[i].a-1)+1; 44 update(a[i].a,d); 45 ans=max(ans,d); 46 } 47 cout<<ans; 48 return 0; 49 }
T2:b
Problem:
给定一个𝑛个点𝑚条边的无向图,每条边有边权。每次询问某一条边不能走的情况下,1到𝑛的最短路。
Code:
1 #include<bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 const int N=100005; 5 const int M=200005; 6 int n,m,S,T; 7 int last[N],nxt[M<<1],to[M<<1],ecnt=1; 8 int w[M<<1]; 9 bool vis[N]; 10 ll distS[N],distT[N]; 11 inline void add(int u,int v,int val){ 12 nxt[++ecnt]=last[u]; 13 last[u]=ecnt; 14 to[ecnt]=v; 15 w[ecnt]=val; 16 nxt[++ecnt]=last[v]; 17 last[v]=ecnt; 18 to[ecnt]=u; 19 w[ecnt]=val; 20 } 21 inline void Dij(int S,ll dist[]){ 22 memset(dist,0x3f,sizeof distS); 23 memset(vis,0,sizeof vis); 24 set<pair<ll,int> > q; 25 q.insert(make_pair(dist[S]=0,S)); 26 while(!q.empty()){ 27 int u=q.begin()->second; 28 q.erase(q.begin()); 29 if(vis[u]) continue; 30 for(int e=last[u],v=to[e];e;v=to[e=nxt[e]]){ 31 if(dist[v]>dist[u]+w[e]){ 32 q.erase(make_pair(dist[v],v)); 33 q.insert(make_pair(dist[v]=dist[u]+w[e],v)); 34 } 35 } 36 } 37 } 38 bool use[N]; 39 struct E{ 40 int v,id; 41 }; 42 vector<E> g[N],rg[N]; 43 bool tree_edge[M],dfned[N]; 44 int pos[N],tot,id[N]; 45 int f[N],pre[N]; 46 void dfs(int u,int fa){ 47 dfned[u]=true; 48 f[u]=fa; 49 id[pos[u]=++tot]=u; 50 for(int e=last[u],v=to[e];e;v=to[e=nxt[e]]){ 51 if(dfned[v]||v==fa) continue; 52 if(distS[v]==distS[u]+w[e]){ 53 dfs(v,u); 54 tree_edge[e>>1]=true; 55 pre[v]=e>>1; 56 g[u].push_back((E){v,e>>1}); 57 } 58 } 59 } 60 bool haveT[N],ban[N]; 61 set<pair<ll,int> > s; 62 int q[N],qn; 63 void dfs_vis(int u){ 64 q[++qn]=u; 65 ban[u]=true; 66 for(int e=0;e<g[u].size();++e){ 67 int v=g[u][e].v; 68 if(ban[v])continue; 69 dfs_vis(v); 70 } 71 } 72 bool ins[M]; 73 ll ans[M]; 74 void solve(){ 75 for(int i=1;i<=m;++i){ 76 if(!tree_edge[i]){ 77 ans[i]=distS[T]; 78 } 79 } 80 haveT[T]=true; 81 for(int o=tot;o>1;--o){ 82 int u=id[o]; 83 if(haveT[u]){ 84 haveT[f[u]]=true; 85 qn=0; 86 dfs_vis(u); 87 for(int i=1;i<=qn;++i){ 88 int p=q[i]; 89 for(int e=last[p],v=to[e];e;v=to[e=nxt[e]]){ 90 if(tree_edge[e>>1]) continue; 91 if(ban[v]){ 92 if(ins[e>>1]){ 93 s.erase(make_pair(distS[p]+w[e]+distT[v],e>>1)); 94 } 95 } 96 else{ 97 s.insert(make_pair(distT[p]+w[e]+distS[v],e>>1)); 98 ins[e>>1]=true; 99 } 100 } 101 } 102 ans[pre[u]]=s.empty()?-1:s.begin()->first; 103 } 104 else{ 105 ans[pre[u]]=distS[T]; 106 } 107 } 108 } 109 signed main(){ 110 S=1; 111 scanf("%d%d",&n,&m); 112 T=n; 113 for(int i=1;i<=m;++i){ 114 int u,v,w; 115 scanf("%d%d%d",&u,&v,&w); 116 add(u,v,w); 117 } 118 Dij(S,distS); 119 Dij(T,distT); 120 if(distS[T]>1e18){ 121 for(int i=1;i<=m;++i) cout<<"-1\n"; 122 return 0; 123 } 124 dfs(S,0); 125 solve(); 126 for(int i=1;i<=m;++i) cout<<ans[i]<<"\n"; 127 return 0; 128 }
T3:c
Problem:
有一个长为𝑛的序列,𝑚次询问,每次询问一个区间内每个数字的(出现次数×数字的值)最大是多少。
Code:
1 #include<bits/stdc++.h> 2 #define int long long 3 using namespace std; 4 const int maxn=100030; 5 int n,m,a[maxn],b[maxn],pos[maxn],sum[maxn]; 6 int cnt[maxn],ans[maxn],pre,now; 7 struct node{ 8 int l,r,lpos,rpos,id; 9 }q[maxn]; 10 bool cmp(node x,node y){ 11 if(x.lpos==y.lpos) return x.r<y.r; 12 else return x.lpos<y.lpos; 13 } 14 inline void add(int id){ 15 int x=a[id]; 16 sum[x]+=b[x]; 17 now=max(now,sum[x]); 18 } 19 inline void del(int id){ 20 int x=a[id]; 21 sum[x]-=b[x]; 22 } 23 signed main(){ 24 scanf("%d%d",&n,&m); 25 int block=sqrt(n); 26 for(int i=1;i<=n;i++){ 27 scanf("%d",&a[i]); 28 b[i]=a[i]; 29 pos[i]=(i-1)/block+1; 30 } 31 sort(b+1,b+1+n); 32 int un=unique(b+1,b+1+n)-b-1; 33 for(int i=1;i<=n;i++){ 34 a[i]=lower_bound(b+1,b+1+un,a[i])-b; 35 } 36 for(int i=1;i<=m;i++){ 37 scanf("%d%d",&q[i].l,&q[i].r); 38 q[i].id=i; 39 q[i].lpos=pos[q[i].l]; 40 q[i].rpos=pos[q[i].r]; 41 } 42 sort(q+1,q+1+m,cmp); 43 int pos=0,l=0,r=1; 44 for(int i=1;i<=m;i++){ 45 int L=q[i].l,R=q[i].r; 46 if(q[i].lpos!=q[i-1].lpos){ 47 memset(sum,0,sizeof(sum)); 48 pre=now=0; 49 l=pos=q[i].lpos*block+1; 50 r=l-1; 51 } 52 if(q[i].lpos==q[i].rpos){ 53 int cur=0; 54 for(int j=L;j<=R;j++){ 55 cnt[a[j]]+=b[a[j]]; 56 cur=max(cur,cnt[a[j]]); 57 } 58 ans[q[i].id]=cur; 59 for(int j=L;j<=R;j++){ 60 cnt[a[j]]-=b[a[j]]; 61 } 62 continue; 63 } 64 while(r<R) add(++r); 65 pre=now; 66 while(l>L) add(--l); 67 ans[q[i].id]=now; 68 while(l<pos) del(l++); 69 now=pre; 70 } 71 for(int i=1;i<=m;i++){ 72 cout<<ans[i]<<endl; 73 } 74 return 0; 75 }

浙公网安备 33010602011771号