赞
踩
目录
相同的日期你只需要统计一次即可,直接dfs剪枝跑就可以了 我的答案235
二分,l=1,r=23333333>>1 ,我的答案11027421
对于最大值,可以根据整除分块定理2知道是a/b,然后取个min就是最大值,对于最小值,二分求,复杂度O(nlogn)
然后其实知道r=a/b,那么也不难推出l是前一个块的r+1,也就是l=a/(b+1)+1 复杂度O(N)
- #include <bits/stdc++.h>
- using namespace std;
- #define ll long long
- #define endl '\n'
- #define x first
- #define y second
- #define pd push_back
- const int maxn=1e4+10;
-
-
- int n;
- ll a[maxn],b[maxn];
-
- void solve()
- {
- cin>>n;
- ll ma=-1,mi=-1;
- for(int i=1;i<=n;i++)
- {
- cin>>a[i]>>b[i];
- ll now=a[i]/b[i];
- if(ma==-1||ma>now)
- {
- ma=now;
- }
- mi=max(mi,(a[i]/(b[i]+1))+1);
- }
- cout<<mi<<" "<<ma;
- }
- int main()
- {
- ios::sync_with_stdio(0);
- cin.tie(0);
- cout.tie(0);
- int tn=1;
- //cin>>tn;
- while(tn--)
- {
- solve();
- }
- return 0;
- }
贪心寄了,还是全排列暴力~~~~~
还是dfs剪枝暴力吧,t<=10,n<=10
- #include <bits/stdc++.h>
- using namespace std;
- #define ll long long
- #define endl '\n'
- #define x first
- #define y second
- #define pd push_back
- const int maxn=1e2+10;
-
- struct node
- {
- int t,d,l;
- } ;
- int n;
- node a[maxn];
- int f[maxn];
- int flag;
- void dfs(int len,int last)
- {
- if(len==n)
- {
- flag=1;
- return;
- }
- for(int i=1;i<=n&&!flag;i++)
- {
- if(f[i])continue;
- auto [t,d,l]=a[i];
- if(last<=t+d)
- {
- f[i]=1;
- dfs(len+1,max(last+l,t+l));
- f[i]=0;
- }
- }
- }
- void solve()
- {
- cin>>n;
- flag=0;
- for(int i=1;i<=n;i++)
- {
- cin>>a[i].t>>a[i].d>>a[i].l;
- f[i]=0;
- }
- dfs(0,-1);
- if(flag)cout<<"YES"<<endl;
- else cout<<"NO"<<endl;
- }
- int main()
- {
- ios::sync_with_stdio(0);
- cin.tie(0);
- cout.tie(0);
- int tn=1;
- cin>>tn;
- while(tn--)
- {
- solve();
- }
- return 0;
- }
考虑dp, dp[i],表示以i结尾的子序列最大长度,当前数字开头为j结尾为i,那么dp[i]=max(dp[i],dp[j]+1);,最后n-最长子序列就可以了,复杂度O(N)
- #include <bits/stdc++.h>
- using namespace std;
- #define ll long long
- #define endl '\n'
- #define x first
- #define y second
- #define pd push_back
- const int maxn=1e5+10;
-
-
- int n;
- int dp[10];
- /*
- 5
- 11 121 22 12 2023
- 1
- */
- void solve()
- {
- cin>>n;
- for(int i=1,j;i<=n;i++)
- {
- cin>>j;
- int f=j,d=j%10;
- while(f>=10)f/=10;
- dp[d]=max(dp[d],dp[f]+1);
- }
- int ma=1;
- for(int i=0;i<10;i++)
- {
- ma=max(ma,dp[i]);
- //cout<<dp[i]<<endl;
- }
- cout<<n-ma<<endl;
- }
- int main()
- {
- ios::sync_with_stdio(0);
- cin.tie(0);
- cout.tie(0);
- int tn=1;
- //cin>>tn;
- while(tn--)
- {
- solve();
- }
- return 0;
- }
先从最外海水跑图,记录外部海水数量,岛的4周海水得有1个方向等于外部海水.否则就是环岛的子岛屿;
跑海水从8个方向染色;
然后跑周围是外部海水的岛屿,四个方向染++cnt,最后输出cnt就是答案
0(N*N)
- #include <bits/stdc++.h>
- #define int int64_t
- #define endl '\n'
- using namespace std;
- const int MAX = 55;
- const int INF = 0x3f3f3f3f3f3f3f3fll;
- const int MOD = 1e9 + 7;
-
- char map_[MAX][MAX]; // 地图
- bool track[MAX][MAX] = {false}; // 访问标记
- bool outsea[MAX][MAX] = {false}; // 外海标记
- struct XY {
- int x, y;
- } nxt[] = {
- {1, 0},
- {-1, 0},
- {0, 1},
- {0, -1},
- {1, 1},
- {-1, 1},
- {1, -1},
- {-1, -1},
- };
-
- void solve() {
- int n, m;
- cin >> n >> m;
- for (int i = 0; i < n; i++) {
- cin >> map_[i];
- }
- for (int i = 0; i < n; i++) {
- for (int j = 0; j < m; j++) {
- track[i][j] = false;
- outsea[i][j] = false;
- }
- }
- // 预处理外海
- for (int i = 0; i < n; i++) {
- for (int j = 0; j < m; j++) {
- if (map_[i][j] == '1' or track[i][j]) continue;
- bool yep = false;
- queue<XY> que, arr;
- track[i][j] = true;
- que.push({i, j});
- arr.push({i, j}); // 记录搜索到的所有海域
- while (not que.empty()) {
- XY pos = que.front();
- que.pop();
- // 注意:海域搜索可以往八个方向走,陆地搜索只能朝四个方向
- for (int i = 0; i < 8; i++) {
- XY nw = {pos.x + nxt[i].x, pos.y + nxt[i].y};
- if (0 <= nw.x and nw.x < n and 0 <= nw.y and nw.y < m) {
- if (map_[nw.x][nw.y] == '0' and track[nw.x][nw.y] == false) {
- track[nw.x][nw.y] = true;
- que.push(nw);
- arr.push(nw);
- }
- } else {
- yep = true; // 如果有一次搜索到地图外,标记此次搜索的所有区域为外海
- }
- }
- }
- if (yep) {
- while (not arr.empty()) {
- XY pos = arr.front();
- arr.pop();
- outsea[pos.x][pos.y] = true; // 标记搜索到的海域为外海
- }
- }
- }
- }
-
- // 别忘了清空访问标记
- for (int i = 0; i < n; i++) {
- for (int j = 0; j < m; j++) {
- track[i][j] = false;
- }
- }
- // 处理岛屿
- int cnt = 0;
- for (int i = 0; i < n; i++) {
- for (int j = 0; j < m; j++) {
- if (map_[i][j] == '0' or track[i][j]) continue;
- bool yep = false;
- queue<XY> que;
- track[i][j] = true;
- que.push({i, j});
- while (not que.empty()) {
- XY pos = que.front();
- que.pop();
- for (int i = 0; i < 4; i++) {
- XY nw = {pos.x + nxt[i].x, pos.y + nxt[i].y};
- if (0 <= nw.x and nw.x < n and 0 <= nw.y and nw.y < m) {
- if (map_[nw.x][nw.y] == '1') {
- if (track[nw.x][nw.y] == false) {
- track[nw.x][nw.y] = true;
- que.push(nw);
- }
- } else {
- if (outsea[nw.x][nw.y]) {
- yep = true; // 搜索到外海为外岛
- }
- }
- } else {
- yep = true; // 搜索到边界外为外岛
- }
- }
- }
- if (yep) {
- cnt++; // 外岛计数
- }
- }
- }
- cout << cnt << endl;
- }
-
- int32_t main() {
- cin.tie(0);
- cout.tie(0);
- ios::sync_with_stdio(0);
-
- int t;
- cin >> t;
- while (t--)
- solve();
-
- return 0;
- }
把c1的位置存起来,对于每个c2位置二分找最小符合的位置,ans加上这个位置下标就可以了
也可以双指针暴力
- #include <bits/stdc++.h>
- using namespace std;
- #define ll long long
- #define endl '\n'
- #define x first
- #define y second
- #define pd push_back
- #define pii pair<int,int>
- const int maxn=5e5+10;
- int n,k;
- char s[maxn],a,b;
- /*
- 4
- abababdb a b
- 4
- ba a b
- */
- void solve()
- {
- cin>>k;
- cin>>s+1;
- cin>>a>>b;
- n=strlen(s+1);
- vector<int>va,vb;
- for(int i=1;i<=n;i++)
- {
- if(s[i]==a)
- {
- va.pd(i);
- }
- if(s[i]==b)
- {
- vb.pd(i);
- }
- }
- va.pd(n+1);
- vb.pd(n+1);
- ll ans=0;
- for(int i=0;i<vb.size()-1;i++)
- {
- int r=lower_bound(va.begin(),va.end(),vb[i]-k+1)-va.begin();
- if(va[r]>vb[i]-k+1)
- {
- r--;
- }
- ans+=r+1;
- //cout<<r+1<<" "<<va[r]<<" "<<vb[i]<<" "<<ans<<endl;
- }
- cout<<ans<<endl;
-
- }
-
- int main()
- {
- ios::sync_with_stdio(0);
- cin.tie(0);
- cout.tie(0);
- int tn=1;
- //cin>>tn;
- while(tn--)
- {
- solve();
- }
- return 0;
- }
线段树+并查集
对于每个点并查集维护左父亲和右父亲。对于每次操作线段树找到最左侧最小下标,然后返回,
这个点的左父亲等于这个点左边的点的左父亲,右同理,然后线段树修改值即可
复杂度 O(KlogN)
可以也采用set存点值和下标,然后+并查集
复杂度也是O(KlogN)
- #include <bits/stdc++.h>
- using namespace std;
- #define ll long long
- #define endl '\n'
- #define x first
- #define y second
- #define pd push_back
- #define pii pair<int,ll>
- const int maxn=5e5+10;
-
-
-
- int n,k;
- ll a[maxn];
- int l[maxn],r[maxn],f[maxn];
- int findl(int x)
- {
- return x==l[x]?x:l[x]=findl(l[x]);
- }
- int findr(int x)
- {
- return x==r[x]?x:r[x]=findr(r[x]);
- }
-
- ll tr[maxn<<4];
- void up(int rt)
- {
- tr[rt]=min(tr[rt<<1],tr[rt<<1|1]);
- }
- void build(int rt,int l,int r)
- {
- tr[rt]=a[l];
- if(l==r)return;
- int mid=l+r>>1;
- build(rt<<1,l,mid);
- build(rt<<1|1,mid+1,r);
- up(rt);
- }
- pii cha(int rt,int l,int r)
- {
- if(l==r)
- {
- return {l,tr[rt]};
- }
- int mid=l+r>>1;
- pii ans;
- if(tr[rt<<1]<=tr[rt<<1|1])
- {
- ans=cha(rt<<1,l,mid);
- }else
- {
- ans=cha(rt<<1|1,mid+1,r);
- }
- return ans;
- }
- void add(int rt,int l,int r,int id,ll val)
- {
- if(id==l&&id==r)
- {
- tr[rt]+=val;
- a[l]=tr[rt];
- return;
- }
- int mid=l+r>>1;
- if(l<=id&&id<=mid)add(rt<<1,l,mid,id,val);
- else if(id>mid&&id<=r)add(rt<<1|1,mid+1,r,id,val);
- up(rt);
- }
- /*
- 5 3
- 1 4 2 8 7
- 5 4
- 1 4 2 8 7
- 5 5
- 1 4 2 8 7
- */
- void solve()
- {
- cin>>n>>k;
- l[0]=0;l[n+1]=0;
- r[0]=0;r[n+1]=0;
- for(int i=1;i<=n;i++)
- {
- cin>>a[i];
- l[i]=i;r[i]=i;
- f[i]=1;
- }
- build(1,1,n);
- while(k--)
- {
- ll mi=1e18,id=-1;
- // for(int i=1;i<=n;i++)//可用线段树优化
- // {
- // if(mi>a[i])
- // {
- // mi=a[i];
- // id=i;
- // }
- // }
- pii i=cha(1,1,n);
- id=i.x;mi=i.y;
- f[id]=0;
- l[id]=findl(l[id-1]);
- r[id]=findr(r[id+1]);
- if(l[id]>=1)add(1,1,n,l[id],mi);
- if(r[id]<=n)add(1,1,n,r[id],mi);
- add(1,1,n,id,1e17);
- // a[l[id]]+=a[id];
- // a[r[id]]+=a[id];
- // a[id]=1e18;
- // for(int i = 1; i <= n; i++)
- // {
- // if(f[i])
- // {
- // cout << a[i] << " ";
- // }
- // }
- // cout<<endl;
- }
- int ff=1;
- for(int i = 1; i <= n; i++)
- {
- if(f[i])
- {
- if(ff)ff=0;
- else cout<<" ";
- cout << a[i] ;
- }
- }
- }
-
- int main()
- {
- ios::sync_with_stdio(0);
- cin.tie(0);
- cout.tie(0);
- int tn=1;
- //cin>>tn;
- while(tn--)
- {
- solve();
- }
- return 0;
- }
倍增,由于要按顺序去游览点,考虑起点那么只有A1,A2,对于2-k的点都是以A1为起点,那么其实路都差不多,假设在这之中p点不去,减去p-1到p的路径值减去p到p+1的路径值,加上p-1到p+1的路径值即可
复杂度O(NlogN+KlogN)
对于加减路径值也可以用树链剖分或lct 复杂度O(NlogN+KlogN)
- #include <bits/stdc++.h>
- using namespace std;
- using ll = long long;
- const int N = 2e5 + 10;
- int h[N], e[N], w[N], ne[N], idx = 0;
- int lg[N], p[N][20], deep[N], a[N];
- ll dis[N], n, k, sum = 0;
- void dfs(int lst, int now) {
- deep[now] = deep[lst] + 1;
- p[now][0] = lst;
- for (int i = 1; (1 << i) <= deep[now]; i++)
- p[now][i] = p[p[now][i - 1]][i - 1];
-
- for (int i = h[now]; i; i = ne[i]) {
- int to = e[i], cost = w[i];
- if (to != lst) {
- dis[to] = dis[now] + cost;
- dfs(now, to);
- }
- }
- }
- int lca(int u, int v) {
- if (deep[u] < deep[v]) swap(u, v);
- while (deep[u] > deep[v])
- u = p[u][lg[deep[u] - deep[v]]];
-
- if (u == v) return u;
- else {
- for (int i = lg[deep[u]]; i >= 0; i--) {
- if (p[u][i] != p[v][i])
- u = p[u][i], v = p[v][i];
- }
- }
- return p[u][0];
- }
- inline void add(int u, int v, int t) {
- e[++idx] = v, w[idx] = t, ne[idx] = h[u], h[u] = idx;
- }
- inline ll ask(int u, int v) {
- if (u == 0 || v == 0) return 0;
- else return dis[u] + dis[v] - 2 * dis[lca(u, v)];
- }
- inline ll query(int i) {
- return ask(a[i - 1], a[i + 1]) - ask(a[i - 1], a[i]) - ask(a[i], a[i + 1]);
- }
- int main() {
- cin >> n >> k;
- for (int i = 1; i < n; i++) {
- int u, v, t;
- cin >> u >> v >> t;
- add(u, v, t);
- add(v, u, t);
- }
- for (int i = 2; i <= n; i++)lg[i] = lg[i >> 1] + 1;
- dfs(0, 1);
- for (int i = 1; i <= k; i++)cin >> a[i];
- for (int i = 2; i <= k; i++)sum += ask(a[i - 1], a[i]);
- for (int i = 1; i <= k; i++)cout << sum + query(i) << ' ';
- }
倍增+树上差分,对于一个数对,我们对数对路径上的值+1,最后看是否有一条边的左右点的点值相等
复杂度O(NlogN+N)
其实要对于数对路径值+1,也可以使用树链剖分来写,这样复杂度也是O(NlogN)
- #include <bits/stdc++.h>
- using namespace std;
- #define ll long long
- #define endl '\n'
- #define x first
- #define y second
- #define pd push_back
- #define pii pair<int,ll>
- const int maxn=1e5+10;
-
-
- struct beizeng
- {
- int dp[22][maxn],deep[maxn];
- int val[maxn];
- vector<int>v[maxn];
- void add(int a,int b)
- {
- v[a].pd(b);
- v[b].pd(a);
- }
- void dfs(int x,int fa)
- {
- //dft[op]=x;
- //df[x]=op++;
- deep[x]=deep[fa]+1;
- dp[0][x]=fa;
- for(int i=1;(1<<i)<=deep[x];i++)
- {
- dp[i][x]=dp[i-1][dp[i-1][x]];
- }
- for(int y:v[x])
- {
- if(y==fa)continue;
- dfs(y,x);
- }
- }
- void dfs2(int x,int fa)
- {
- for(int y:v[x])
- {
- if(y==fa)continue;
- dfs2(y,x);
- val[x]+=val[y];
- }
- }
- int lca(int a,int b)
- {
- if(deep[a]>deep[b])swap(a,b);
- for(int i=20;i>=0;i--)
- {
- if(deep[a]<=deep[b]-(1<<i))
- b=dp[i][b];
- }
- if(a==b)
- return a;
- for(int i=20;i>=0;i--)
- {
- if(dp[i][a]!=dp[i][b])
- {
- a=dp[i][a];
- b=dp[i][b];
- }
- }
- return dp[0][a];
- }
- }tree;
- int n,m;
- int a[maxn],b[maxn];
- void solve()
- {
- cin>>n>>m;
- for(int i=1;i<n;i++)
- {
- cin>>a[i]>>b[i];
- tree.add(a[i],b[i]);
- }
- tree.dfs(1,0);
- for(int i=1;i<=m;i++)
- {
- int x,y;
- cin>>x>>y;
- int c=tree.lca(x,y);
- tree.val[x]++;tree.val[y]++;
- tree.val[c]--;tree.val[tree.dp[0][c]]--;
- }
- tree.dfs2(1,0);
- int ans=-1;
- for(int i=n-1;i>=1;i--)
- {
- if(tree.val[a[i]]==m&&tree.val[b[i]]==m)
- {
- ans=i;
- break;
- }
- }
- cout<<ans<<endl;
- }
-
- int main()
- {
- ios::sync_with_stdio(0);
- cin.tie(0);
- cout.tie(0);
- int tn=1;
- //cin>>tn;
- while(tn--)
- {
- solve();
- }
- return 0;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。