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 }
posted @ 2021-10-09 21:41  B_lank  阅读(49)  评论(0)    收藏  举报