D. Fragmentation merging
题意:自己看
题解:对每一种情况进行判断,看是不是由最多两段组成就行了
AC代码
#include "bits/stdc++.h" using namespace std; #define ll long long const int maxn=5e3+10; const int inf=0x3f3f3f3f; inline int rd(){ int a; scanf("%d",&a); return a; } int t; int n,m; int vis[maxn],a[maxn]; int main() { t=rd(); while(t--) { n=rd(); for(int i=1;i<=n;i++){ int aa=rd(); a[aa]=i; } if(n==1){ printf("0\n"); continue; } ll res=0; for(int i=1;i<=n;i++){ int cnt=0; for(int j=1;j<=5005;j++)vis[j]=0;//初始化 for(int j=i;j<=n;j++) { if (vis[a[j] - 1] && vis[a[j] + 1]) {//该点左右两边都已经加入,就将这两段合并 cnt--; } else if (vis[a[j] - 1] || vis[a[j] + 1]) {//该点加入左边或右边 //*别做任何处理 } else cnt++;//新建一段 vis[a[j]]=1; if(cnt<=2)res++; } } printf("%lld\n",res); } return 0; }
I. Sequence
题意:自己看
题解:把一维的ABLR转化成二维的坐标,然后就可以了
对于每一种情况进行数矩形的个数来判断,就能转化成单调栈求矩形个数的问题
方法一:容斥定理(容易MLE)
#include "bits/stdc++.h" using namespace std; //#define int long long #define ll long long inline int rd(){ int a; scanf("%d",&a); return a; } const int N=5001; ll maxn,sum; short last[N][N]; int f[N][N]; short n,a[N][N]; int m; vector<short> s[N]; int main() { scanf("%d %d",&n,&m); for (int i=1;i<=m;i++){ int aa=rd(),ab=rd(); a[aa][ab]=1; } for (int i=1;i<=n;i++) s[i].push_back(0); for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) { if (a[i][j]) last[i][j]=j; else last[i][j]=last[i][j-1]; while (s[j].size()>1 && last[s[j].back()][j]<last[i][j]) s[j].pop_back(); maxn+=i*j; f[i][j]=f[s[j].back()][j]+(i-s[j].back())*last[i][j]; sum+=f[i][j]; s[j].push_back(i); } printf("%lld\n",maxn-sum); return 0; }