比赛链接:https://codeforces.com/contest/1216
题意:给出三个长方形的横纵坐标 (左下角和右上角),问后两个长方形是否将第一个完全覆盖;
思路:将坐标离散化,用二维数组模拟染色判断;(代码写的很丑。。)
#include
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int N=2e5+10;
struct node
{
int x,y,k,id;
} q[10];
bool cmp1(node x,node y)
{
return x.x
题意:规定一个序列,q此询问,每次询问序列第k个的数值;
规定的序列是:112123123412345……;
思路:记录每个数字构成串的长度 例如 a[10]=11 (12345678910,长度为11),记录每个数字构成串的长度的前缀和,例如
sum[5]=a[1]+a[2]+a[3]+a[4]+a[5]=15;然后二分再二分,第一个二分找是第几个数字构成的串,第二次二分是具体数字;
#include
using namespace std;
typedef long long ll;
const ll inf=0x3f3f3f3f3f3f3f3f;
const int N=8e4+10;
ll sum[N],a[N],b[N];
int main()
{
for(ll i=1;i<=30000;i++)
{
if(i>=10000) a[i]=a[i-1]+5;
else if(i>=1000) a[i]=a[i-1]+4;
else if(i>=100) a[i]=a[i-1]+3;
else if(i>=10) a[i]=a[i-1]+2;
else a[i]=a[i-1]+1;
sum[i]=sum[i-1]+a[i];
}
printf("%lld\n",sum[30000]);
ll q,k;
scanf("%lld",&q);
for(ll i=1;i<=q;i++)
{
scanf("%lld",&k);
ll tmp=lower_bound(sum+1,sum+30000,k)-sum,e=0;
k=k-sum[tmp-1];
ll t=lower_bound(a+1,a+30000,k)-a;
if(a[t-1]==k)
{
k=k-a[t-1]+1;
t--;
}
else k=k-a[t-1];
while(t)
{
ll x=t%10;
t/=10;
b[++e]=x;
}
printf("%lld\n",b[e-k+1]);
}
return 0;
}
题意:有n间宿舍编号1~n,要给没间宿舍联网,可以直接联网,有的宿舍安放了路由器,路由器可以覆盖(i-k,i+k)宿舍,别的宿舍安置的路由器联网,第 i 个宿舍直接联网需要花费 i 元,被路由器覆盖不花钱,路由器也需要联网才能使用,第 i 个房间的路由器联网花费需要 i 元,问网覆盖全部宿舍的最少花费;
/*
思路:dp[i][0]表示前i间宿舍通过直接联网需要的最小花费;
dp[i][1]表示如果第i间宿舍有路由器,并且路由器联网的前i间宿舍的最小花费;
没有路由器的宿舍,可以通过 i-k~i-1 间宿舍的路由器联网;
有路由器的宿舍,可以通过线段树找 i-k-1~i-1之间的最小花费来更新;
*/
#include
using namespace std;
typedef long long ll;
const ll inf=0x3f3f3f3f3f3f3f3f;
const int N=2e5+10;
char str[N];
ll a[2][N*4],dp[N][2];
void build(ll *tree,ll a,ll b,ll r)
{
tree[r]=inf;
if(a==b) return;
ll mid=(a+b)/2;
build(tree,a,mid,r<<1);
build(tree,mid+1,b,r<<1|1);
tree[r]=min(tree[r<<1],tree[r<<1|1]);
}
void update(ll *tree,ll a,ll b,ll r,ll val,ll qa)
{
if(a==b)
{
tree[r]=val;
return;
}
ll mid=(a+b)/2;
if(qa<=mid) update(tree,a,mid,r<<1,val,qa);
else update(tree,mid+1,b,r<<1|1,val,qa);
tree[r]=min(tree[r<<1],tree[r<<1|1]);
}
ll query(ll *tree,ll a,ll b,ll r,ll qa,ll qb)
{
if(a>=qa&&b<=qb) return tree[r];
ll mid=(a+b)/2,res=inf;
if(qa<=mid) res=min(res,query(tree,a,mid,r<<1,qa,qb));
if(qb>mid) res=min(res,query(tree,mid+1,b,r<<1|1,qa,qb));
return res;
}
int main()
{
ll n,k;
scanf("%lld %lld",&n,&k);
scanf("%s",str+1);
build(a[0],1,n,1);
build(a[1],1,n,1);
dp[n][1]=inf;
dp[0][0]=0;
for(ll i=1;i<=n;i++)
{
if(i>1) dp[i][0]=min(i+dp[i-1][0],query(a[1],1,n,1,i-k,i-1));
else dp[i][0]=i;
update(a[0],1,n,1,dp[i][0],i);
if(str[i]=='1')
{
if(i-k<=1) dp[i][1]=i;
else if(i>1) dp[i][1]=min(query(a[0],1,n,1,i-k-1,i-1),query(a[1],1,n,1,i-k-1,i-1))+i;
update(a[1],1,n,1,dp[i][1],i);
}
}
printf("%lld\n",min(dp[n][1],dp[n][0]));
return 0;
}