题目链接
A.枚举位数,然后判断一下即可。。。。
ps:好像并不需要二分。。。不过问题不大
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e5 + 10;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
int t;
LL n,x;
int get(LL y){
int cnt=0;
while(y){
cnt++;
y/=10;
}
return cnt;
}
LL fac[33];
int main() {
ios::sync_with_stdio(false);
//5 6 7 8 9 10 11 12
fac[0]=1;
for(int i=1;i<=17;i++){
fac[i]=fac[i-1]*10;
}
for(cin>>t;t;t--){
cin>>n>>x;
int num=get(x),sta=1;
LL tot=0,ans=0;
for(int i=num;;i++){
LL dis=(fac[i]-x)*i;
if(tot+dis<n){
tot+=dis;
ans+=(fac[i]-x);
x=fac[i];
}else{
LL l=0,r=fac[i]-x,need=0;
while(l<=r){
LL mid=l+r>>1;
if(mid*i+tot<=n)need=mid,l=mid+1;
else r=mid-1;
}
tot+=need*i;
ans+=need;
break;
}
}
if(tot<n)sta=0;
if(sta)cout<<ans<<'\n';
else cout<<-1<<'\n';
}
return 0;
}
C.输入输出题
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e5 + 10;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
int t,n,p,k;
int main() {
ios::sync_with_stdio(false);
for(cin>>t;t;t--){
cin>>k>>p>>n;
cout<<1ll*n*max(k-p,0)<<'\n';
}
return 0;
}
D.二进制枚举,加bitset优化。。。。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e5 + 10;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
int t,n,m;
int main() {
ios::sync_with_stdio(false);
for(cin>>t;t;t--){
cin>>n>>m;
bitset<22>vis[n+1];
for(int i=1;i<=n;i++)vis[i].reset();
for(int i=1;i<=m;i++){
int s,t;
cin>>s>>t;
vis[s].set(t-1);
}
int ans=n;
for(int i=0;i<(1<<n);i++){
vector<int>v;
bitset<22>g;
g.reset();
for(int j=0;j<n;j++)g.set(j);
int res=0;
for(int j=0;j<n;j++){
if(1<<j&i){
res++;
g&=vis[j+1];
}
}
ans=max(ans,res+(int)g.count());
}
cout<<ans<<'\n';
}
return 0;
}
G.把每个点连的边按权值由大到小排序。
把询问存起来,递增排序,在树上模拟模拟即可。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e5 + 10;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
int t,n,q,a[N];
LL ans;
vector<pair<int,int>>v[N];
int dfs(int x,int y,int l,int r){
int _r=r;
//cout<<x<<' '<<l<<' '<<r<<endl;
for(auto k:v[x])if(k.se!=y){
int da=k.fi;
if(l>r)break;
auto f=upper_bound(a+l,a+r+1,da)-a;
if(k.se!=y)dfs(k.se,x,f,r);
r=f-1;
}
//cout<<x<<' '<<l<<' '<<r<<endl;
if(l<=r){
ans+=1ll*(r-l+1)*x;
}
}
int main() {
for(scanf("%d",&t);t;t--){
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++)v[i].clear();
for(int i=1;i<n;i++){
int s,t,w;
scanf("%d%d%d",&s,&t,&w);
v[s].pb({w,t});
v[t].pb({w,s});
}
for(int i=1;i<=n;i++)
sort(v[i].begin(),v[i].end(),[](pair<int,int>x,pair<int,int>y){return x.fi>y.fi;});
ans=0;
for(int i=1;i<=q;i++){
int x;
scanf("%d",&a[i]);
}
sort(a+1,a+1+q);
dfs(1,0,1,q);
printf("%lld\n",ans);
}
return 0;
}
I.显然要求一组 正反字典序都递减的最大集。
那么先按正着排序,然后把反着的字典序离散化之后跑最长不递增子序列即可。
注意,要求连续的两个必须有且只有一个包含字符m。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e5 + 10;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
int _,n;
int id[N],f[N];
void add(int *t,int x,int y){
for(;x;x-=x&-x)t[x]=max(t[x],y);
}
int get(int *t,int x){
int to=0;
for(;x<=n;x+=x&-x)to=max(t[x],to);
return to;
}
int t1[N],t2[N],vis[N];
string a[N],b[N],c[N];
int main() {
ios::sync_with_stdio(false);
for(cin>>_;_;_--){
cin>>n;int st=0;
for(int i=0;i<=n;i++)f[i]=0,vis[i]=t1[i]=t2[i]=0;
for(int i=1;i<=n;i++){
cin>>a[i];
}
sort(a+1,a+1+n,[](string x,string y){return x>y;});
for(int i=1;i<=n;i++){
for(auto x:a[i]){
vis[i]|=x=='m';
}
st|=vis[i];
}
for(int i=1;i<=n;i++){
b[i]=a[i];
reverse(b[i].begin(),b[i].end());
c[i]=b[i];
}
sort(c+1,c+1+n);
int len=unique(c+1,c+1+n)-c-1;
for(int i=1;i<=n;i++)id[i]=lower_bound(c+1,c+1+len,b[i])-c;
int ans=1;
for(int i=1;i<=n;i++){
if(vis[i]){
f[i]=get(t2,id[i])+1;
add(t1,id[i],f[i]);
}else{
f[i]=get(t1,id[i])+1;
add(t2,id[i],f[i]);
}
ans=max(ans,f[i]);
}
cout<<ans<<'\n';
}
return 0;
}
L.显然这种题就是要算贡献,即每个数被加了或减了几次。
用单调栈可以很好的维护出来。
具体:枚举上下边界,把这个矩形压成一维,值由每列的最大最小值代替,单调栈维护每个值的作用区间(即这个区间的最值就是自己)即可。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e5 + 10;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
int t,n;
int a[555][555];
int mn[555],mx[555];
int q[555],h=0;
int l1[555],r1[555],l2[555],r2[555];
void get(){
for(int i=1;i<=n;i++)l1[i]=r1[i]=l2[i]=r2[i]=0;
h=0;
mn[n+1]=0;
q[++h]=1;
l1[1]=1;
for(int i=2;i<=n+1;i++){
while(h>=1&&mn[q[h]]>=mn[i]){
r1[q[h]]=i-1;
--h;
}
l1[i]=q[h]+1;
q[++h]=i;
}
h=0;
q[++h]=1;
l2[1]=1;
mx[n+1]=555;
for(int i=2;i<=n+1;i++){
while(h>=1&&mx[q[h]]<=mx[i]){
r2[q[h]]=i-1;
--h;
}
l2[i]=q[h]+1;
q[++h]=i;
}
}
int main() {
for(scanf("%d",&t);t;t--){
scanf("%d",&n);
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
scanf("%d",&a[i][j]);
}
}
LL tot=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++)mn[j]=555,mx[j]=0;
for(int j=i;j<=n;j++){
for(int k=1;k<=n;k++){
mn[k]=min(mn[k],a[j][k]);
mx[k]=max(mx[k],a[j][k]);
}
get();
for(int k=1;k<=n;k++){
tot-=1ll*mn[k]*(k-l1[k]+1)*(r1[k]-k+1);
tot+=1ll*mx[k]*(r2[k]-k+1)*(k-l2[k]+1);
}
}
}
printf("%lld\n",tot);
}
return 0;
}