凸多边形切割问题:线段树模拟可以做
- 优弧与劣弧分两种情况考虑
- 最后结束点一定是起始点
- 线段树tree_add需要四个参数,tree_sum需要五个参数
- 线段树所用空间不超maxn*4
#include <cstdio>
#include <cstring>
using namespace std;
#define maxn 1000005
int node[maxn];
long long tree[maxn*4];
void tree_add(int now,int l,int r,int key)
{
tree[now]++;
if(l==r) return ;
int mid = (l+r)/2;
if(key>mid)
tree_add(now*2+2,mid+1,r,key);
else
tree_add(now*2+1,l,mid,key);
}
long long tree_sum(int now,int l,int r,int keyl,int keyr)
{
if(l==keyl&&r==keyr) return tree[now];
int mid = (l+r)/2;
if(keyl>mid)
return tree_sum(now*2+2,mid+1,r,keyl,keyr);
else if(keyr<=mid)
return tree_sum(now*2+1,l,mid,keyl,keyr);
else
return tree_sum(now*2+1,l,mid,keyl,mid)+tree_sum(now*2+2,mid+1,r,mid+1,keyr);
}
int main()
{
memset(node,0,sizeof(node));
memset(tree,0,sizeof(tree));
int N,k;
scanf("%d%d",&N,&k);
long long ans = 1;
int loc = 0;
int nloc = loc+k;
node[loc] = 1;
while(node[nloc]==0)
{
node[nloc] = 1;
tree_add(0,0,N-1,loc);
tree_add(0,0,N-1,nloc);
ans++;
if(nloc<loc)
{
if(k>N/2)
ans+=tree_sum(0,0,N-1,nloc+1,loc-1);
else
{
ans+=tree_sum(0,0,N-1,0,nloc-1);
if(loc!=N-1)
ans+=tree_sum(0,0,N-1,loc+1,N-1);
}
}else
if(k>N/2){
if(loc!=0)
ans += tree_sum(0,0,N-1,0,loc-1);
if(nloc!=N-1)
ans+=tree_sum(0,0,N-1,nloc+1,N-1);
}else
ans+=tree_sum(0,0,N-1,loc+1,nloc-1);
loc = nloc;
nloc = (nloc+k)%N;
printf("%I64d ",ans);
}
ans++;
if(k>N/2)
ans+=tree_sum(0,0,N-1,1,loc-1);
else
ans+=tree_sum(0,0,N-1,loc+1,N-1);
printf("%I64d\n",ans);
return 0;
}
封装后代码
#include <cstdio>
#include <cstring>
#define maxn 1000005
int node[maxn];
long long tree[maxn*4];
/*
the segment gnum must full binary tree,
the left child is loc*2+1,
and the right child is loc*2+2.
#define maxn 1000005
int gnode[maxn];
long long gnum[maxn*4];
*/
void GxdSegmentTreeAdd(long long* gnum,int glen,int gfl,int gfr,int gnow,int gkeyloc)
{
gnum[gnow]++;
if(gfl==gfr) return ;
int mid = (gfl+gfr)/2;
if(gkeyloc>mid) GxdSegmentTreeAdd(gnum,glen,mid+1,gfr,gnow*2+2,gkeyloc);
else GxdSegmentTreeAdd(gnum,glen,gfl,mid,gnow*2+1,gkeyloc);
}
long long GxdSegmentTreeSearch(long long* gnum,int glen,int gfl,int gfr,int gnow,int gkeyl,int gkeyr)
{
if(gfl==gkeyl&&gfr==gkeyr) return tree[gnow];
int mid = (gfl+gfr)/2;
if(gkeyl>mid) return GxdSegmentTreeSearch(gnum,glen,mid+1,gfr,gnow*2+2,gkeyl,gkeyr);
else if(gkeyr<=mid) return GxdSegmentTreeSearch(gnum,glen,gfl,mid,gnow*2+1,gkeyl,gkeyr);
else return GxdSegmentTreeSearch(gnum,glen,gfl,mid,gnow*2+1,gkeyl,mid)+GxdSegmentTreeSearch(gnum,glen,mid+1,gfr,gnow*2+2,mid+1,gkeyr);
}
int main()
{
memset(node,0,sizeof(node));
memset(tree,0,sizeof(tree));
int N,k;
scanf("%d%d",&N,&k);
long long ans = 1;
int loc = 0;
int nloc = loc + k;
node[loc] = 1;
while(node[nloc]==0)
{
node[nloc] = 1;
GxdSegmentTreeAdd(tree,maxn*4,0,N-1,0,loc);
GxdSegmentTreeAdd(tree,maxn*4,0,N-1,0,nloc);
ans++;
if(nloc<loc)
{
if(k>N/2)
ans+=GxdSegmentTreeSearch(tree,maxn*4,0,N-1,0,nloc+1,loc-1);
else
{
ans+=GxdSegmentTreeSearch(tree,maxn*4,0,N-1,0,0,nloc-1);
if(loc!=N-1)
ans+=GxdSegmentTreeSearch(tree,maxn*4,0,N-1,0,loc+1,N-1);
}
}else
if(k>N/2){
if(loc!=0)
ans += GxdSegmentTreeSearch(tree,maxn*4,0,N-1,0,0,loc-1);
if(nloc!=N-1)
ans+=GxdSegmentTreeSearch(tree,maxn*4,0,N-1,0,nloc+1,N-1);
}else
ans+=GxdSegmentTreeSearch(tree,maxn*4,0,N-1,0,loc+1,nloc-1);
loc = nloc;
nloc = (nloc+k)%N;
printf("%I64d ",ans);
}
ans++;
if(k>N/2)
ans+=GxdSegmentTreeSearch(tree,maxn*4,0,N-1,0,1,loc-1);
else
ans+=GxdSegmentTreeSearch(tree,maxn*4,0,N-1,0,loc+1,N-1);
printf("%I64d\n",ans);
return 0;
}