STARS
数星星
#include <cstdio>
#define LowBit(A) ((A)&(-A))
const long maxr = 32010;
const long maxn = 15010;
long tree[maxr];
long cnt[maxn];
void insert(long a)
{
for (long i=a;i<maxr;i+=LowBit(i))
tree[i]++;
}
long find(long a)
{
long ans = 0;
for (long i=a;i>0;i-=LowBit(i))
ans += tree[i];
return ans;
}
int main()
{
long n;
scanf("%ld",&n);
for (long i=1;i<n+1;i++)
{
long x;long y;
scanf("%ld%ld",&x,&y);
x++;y++;
cnt[find(x)]++;
insert(x);
}
for (long i=0;i<n;i++)
printf("%ld ",cnt[i]);
return 0;
}
#include <cstdio>
const long maxr=32000;
const long maxn=15000;
long tree[maxr*4+10];
long cnt[maxn+10];
void insert(long l,long r,long i,long a)
{
long mid = (l+r)>>1;
if (l == r)
{
tree[i] ++;
return;
}
if (a > mid)
{
insert(mid+1,r,(i<<1)+1,a);
}
if (a <= mid)
{
insert(l,mid,(i<<1),a);
}
tree[i] = tree[i<<1]+tree[(i<<1)+1];
}
long find(long l,long r,long i,long ll,long rr)
{
long mid = (l+r)>>1;
if (l>=ll && r<=rr)
{
return tree[i];
}
else if (rr <= mid)
{
return find(l,mid,i<<1,ll,rr);
}
else if (ll > mid)
{
return find(mid+1,r,(i<<1)+1,ll,rr);
}
else
{
return find(l,mid,i<<1,ll,mid) + find(mid+1,r,(i<<1)+1,mid+1,rr);
}
}
long maxans=0;
#define MAX(a,b) ((a)>(b)?(a):(b))
int main()
{
long n;
scanf("%ld",&n);
for (long i=1;i<n+1;i++)
{
long x;long y;
scanf("%ld%ld",&x,&y);
long ans = find(0,maxr,1,0,x);
cnt[ans] ++;
insert(0,maxr,1,x);
}
for (long i=0;i<n;i++)
{
printf("%ld ",cnt[i]);
}
return 0;
}
两个版本对拍中各发现了一个问题。。线段树的版本,没有考虑同一个点重复添加。。树状数组必须从1开始,不能从0开始,会死循环
序列操作
#include <cstdio>
struct node
{
long col;
long count;
long rmax;
long lmax;
long max;
};
const long maxn = 100010;
node tree[maxn*4+10];
long L[maxn*4+10];
long R[maxn*4+10];
long n;long m;
#define MIN(a,b) ((a)<(b)?(a):(b))
#define MAX(a,b) ((a)>(b)?(a):(b))
void updata(long i)
{
if (tree[i<<1].col==tree[(i<<1)+1].col && tree[i<<1].col < 2)
tree[i].col = tree[i<<1].col;
else
tree[i].col = 2;
tree[i].count = tree[i<<1].count + tree[(i<<1)+1].count;
tree[i].lmax = tree[i<<1].lmax;
if (tree[i<<1].col == 1)
tree[i].lmax = tree[i<<1].count+tree[(i<<1)+1].lmax;
tree[i].rmax = tree[(i<<1)+1].rmax;
if (tree[(i<<1)+1].col == 1)
tree[i].rmax = tree[(i<<1)+1].count+tree[i<<1].rmax;
tree[i].max = MAX(tree[i<<1].max,tree[(i<<1)+1].max);
tree[i].max = MAX(tree[i].max,tree[i<<1].rmax+tree[(i<<1)+1].lmax);
}
void updata(node& n,const node& n1,const node& n2)
{
if (n1.col==n2.col && n1.col < 2)
n.col = n1.col;
else
n.col = 2;
n.count = n1.count + n2.count;
n.lmax = n1.lmax;
if (n1.col == 1)
n.lmax = n1.count+n2.lmax;
n.rmax = n2.rmax;
if (n2.col == 1)
n.rmax = n2.count+n1.rmax;
n.max = MAX(n1.max,n2.max);
n.max = MAX(n.max,n1.rmax+n2.lmax);
}
void insert(long i,long k,long a)
{
long l = L[i];
long r = R[i];
long mid = (l+r)>>1;
if (l == r)
{
tree[i].col = a;
tree[i].count = a;
tree[i].lmax = a;
tree[i].rmax = a;
tree[i].max = a;
return;
}
if (k <= mid)
insert(i<<1,k,a);
else if(k > mid)
insert((i<<1)+1,k,a);
updata(i);
}
inline void pass(long i)
{
if (tree[i].col < 2)
{
tree[i<<1].col = tree[i].col;
tree[(i<<1)+1].col = tree[i].col;
tree[(i<<1)+1].count = tree[i].count>>1;
tree[i<<1].count = tree[i].count-tree[(i<<1)+1].count;
if (tree[i].col == 1)
{
tree[i<<1].lmax = tree[i<<1].rmax = tree[i<<1].max = R[i<<1]-L[i<<1]+1;
tree[(i<<1)+1].lmax = tree[(i<<1)+1].rmax = tree[(i<<1)+1].max = R[(i<<1)+1]-L[(i<<1)+1]+1;
}
else
{
tree[i<<1].lmax = tree[i<<1].rmax = tree[i<<1].max = 0;
tree[(i<<1)+1].lmax = tree[(i<<1)+1].rmax = tree[(i<<1)+1].max = 0;
}
}
}
void set0(long i,long ll,long rr)
{
long l = L[i];
long r = R[i];
long mid = (l+r)>>1;
if (ll<=l && rr>=r)
{
tree[i].col = 0;
tree[i].count = 0;
tree[i].max=tree[i].lmax=tree[i].rmax=0;
return;
}
else if (rr < mid+1)
{
pass(i);
set0(i<<1,ll,rr);
}
else if (ll > mid)
{
pass(i);
set0((i<<1)+1,ll,rr);
}
else
{
pass(i);
set0(i<<1,ll,mid);
set0((i<<1)+1,mid+1,rr);
}
updata(i);
}
void set1(long i,long ll,long rr)
{
long l = L[i];
long r = R[i];
long mid = (l+r)>>1;
if (ll<=l && rr>=r)
{
tree[i].col = 1;
tree[i].count = R[i]-L[i]+1;
tree[i].max=tree[i].lmax=tree[i].rmax=tree[i].count;
return;
}
else if (rr < mid+1)
{
pass(i);
set1(i<<1,ll,rr);
}
else if (ll > mid)
{
pass(i);
set1((i<<1)+1,ll,rr);
}
else
{
pass(i);
set1(i<<1,ll,mid);
set1((i<<1)+1,mid+1,rr);
}
updata(i);
}
void rev(long i,long ll,long rr)
{
long l = L[i];
long r = R[i];
long mid = (l+r)>>1;
if (ll<=l&&rr>=r && tree[i].col<2)
{
tree[i].col ^= 1;
if (tree[i].count)
tree[i].count=0;
else
tree[i].count=R[i]-L[i]+1;
tree[i].lmax=tree[i].rmax=tree[i].max=tree[i].count;
return;
}
else if (rr<mid+1)
{
pass(i);
rev(i<<1,ll,rr);
}
else if(ll>mid)
{
pass(i);
rev((i<<1)+1,ll,rr);
}
else
{
pass(i);
rev(i<<1,ll,rr);
rev((i<<1)+1,ll,rr);
}
updata(i);
}
long count(long i,long ll,long rr)
{
long l = L[i];
long r = R[i];
long mid = (l+r)>>1;
if (ll<=l && rr>=r)
{
return tree[i].count;
}
if (rr < mid+1)
{
pass(i);
return count(i<<1,ll,rr);
}
if (ll > mid)
{
pass(i);
return count((i<<1)+1,ll,rr);
}
else
{
pass(i);
return count(i<<1,ll,mid)+count((i<<1)+1,mid+1,rr);
}
}
node longest(long i,long ll,long rr)
{
long l = L[i];
long r = R[i];
long mid = (l+r)>>1;
if (ll<=l && rr>=r)
{
pass(i);
return tree[i];
}
if (rr < mid+1)
{
pass(i);
return longest(i<<1,ll,rr);
}
else if (ll > mid)
{
pass(i);
return longest((i<<1)+1,ll,rr);
}
else
{
pass(i);
node rv1 = longest(i<<1,ll,mid);
node rv2 = longest((i<<1)+1,mid+1,rr);
node rv; updata(rv,rv1,rv2);
return rv;
}
}
void build(long l,long r,long i)
{
long mid=(l+r)>>1;
L[i] = l;R[i] = r;
if (l == r)
return;
build(l,mid,i<<1);
build(mid+1,r,(i<<1)+1);
}
int main()
{
// freopen("operation.in","r",stdin);
// freopen("operation.out","w",stdout);
scanf("%ld%ld",&n,&m);
build(0,n-1,1);
for (long i=0;i<n;i++)
{
long _a;
scanf("%ld",&_a);
insert(1,i,_a);
}
node _tn;
while ( m -- )
{
long i;long a;long b;
scanf("%ld%ld%ld",&i,&a,&b);
switch(i)
{
case 0:
set0(1,a,b);
break;
case 1:
set1(1,a,b);
break;
case 2:
rev(1,a,b);
break;
case 3:
printf("%ld\n",count(1,a,b));
break;
case 4:
_tn = longest(1,a,b);
printf("%ld\n",_tn.max);
}
}
return 0;
}
#include <cstdio>
long n;long m;
long que[100010];
const long inf = 0x7f7f7f7f;
#define MIN(a,b) ((a)<(b)?(a):(b))
#define MAX(a,b) ((a)>(b)?(a):(b))
int main()
{
// freopen("operation.in","r",stdin);
// freopen("operation.out","w",stdout);
scanf("%ld%ld",&n,&m);
for (long i=0;i<n;i++)
scanf("%ld",que+i);
long _cnt = 0;
long ans = -inf;
while (m--)
{
long c;long a;long b;
scanf("%ld%ld%ld",&c,&a,&b);
switch(c)
{
case 0:
for (long i=a;i<b+1;i++)
que[i] = 0;
break;
case 1:
for (long i=a;i<b+1;i++)
que[i] = 1;
break;
case 2:
for (long i=a;i<b+1;i++)
que[i] ^= 1;
break;
case 3:
_cnt = 0;
for (long i=a;i<b+1;i++)
_cnt += que[i];
printf("%ld\n",_cnt);
break;
case 4:
_cnt = 0;
ans = 0;
for (long i=a;i<b+1;i++)
{
if (que[i]-1) continue;
long j = i+1;
while (j<=b && que[j]==que[i])j++;
_cnt = j-i;
ans = MAX(_cnt,ans);
i = j;
}
printf("%ld\n",ans);
break;
}
}
return 0;
}
比原来的代码长。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
达不到比赛要求了。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
Longest中忘了向下传了。
注意col等于0或1是懒标记,2不是懒标记。
写了两个Updata,改了一个又忘了改另一个。
insert的时候,每一个元素都设成了1,但是有可能全是0。
简单题
TLE 80
#include <string>
#include <cstdio>
long count[400010];
long n;long m;
void pass(long i)
{
if (count[i]>-1)
{
count[i<<1] = count[i];
count[(i<<1)+1] = count[i];
}
}
void reverse(long l,long r,long i,long ll,long rr)
{
long mid = (l+r) >> 1;
if (ll<=l && rr>=r && count[i]>-1)
{
count[i]^=1;
return;
}
if (rr <= mid)
{
if (count[i]>-1)
{
count[i<<1] = count[i];
count[(i<<1)+1] = count[i];
}
reverse(l,mid,i<<1,ll,rr);
}
if (ll > mid)
{
if (count[i]>-1)
{
count[i<<1] = count[i];
count[(i<<1)+1] = count[i];
}
reverse(mid+1,r,(i<<1)+1,ll,rr);
}
if (ll <= mid && rr > mid)
{
if (count[i]>-1)
{
count[i<<1] = count[i];
count[(i<<1)+1] = count[i];
}
reverse(l,mid,i<<1,ll,mid);
reverse(mid+1,r,(i<<1)+1,mid+1,rr);
}
if (count[i<<1] == count[(i<<1)+1] && count[i<<1]>-1)
count[i] = count[i<<1];
else
count[i] = -1;
}
long find(long l,long r,long i,long v)
{
long mid = (l+r)>>1;
if (count[i] > -1)
return count[i];
if (v < mid+1)
{
if (count[i]>-1)
{
count[i<<1] = count[i];
count[(i<<1)+1] = count[i];
}
return find(l,mid,i<<1,v);
}
if (v > mid)
{
if (count[i]>-1)
{
count[i<<1] = count[i];
count[(i<<1)+1] = count[i];
}
return find(mid+1,r,(i<<1)+1,v);
}
}
inline int getint()
{
int res = 0; char tmp; bool sgn = 1;
do tmp = getchar();
while (!isdigit(tmp) && tmp != '-');
if (tmp == '-')
{
sgn = 0;
tmp = getchar();
}
do res = (res << 1) + (res << 3) + tmp - '0';
while (isdigit(tmp = getchar()));
return sgn ? res : -res;
}
int main()
{
freopen("easy.in","r",stdin);
freopen("easy.out","w",stdout);
n = getint();
m = getint();
for (long i=1;i<m+1;i++)
{
long t;long l;long r;
t = getint();
if (t == 1)
{
l = getint();
r = getint();
if (l > r) continue;
reverse(1,n,1,l,r);
}
else
{
l = getint();
long tmp = find(1,n,1,l);
if (tmp & 1)
printf("1\n");
else
printf("0\n");
}
}
return 0;
}
AC
#include <string>
#include <cstdio>
long count[400010];
long n;long m;
void reverse(long l,long r,long i,long ll,long rr)
{
long mid = (l+r) >> 1;
if (ll<=l && rr>=r)
{
count[i]^=1;
return;
}
if (rr <= mid)
{
reverse(l,mid,i<<1,ll,rr);
}
if (ll > mid)
{
reverse(mid+1,r,(i<<1)+1,ll,rr);
}
if (ll <= mid && rr > mid)
{
reverse(l,mid,i<<1,ll,mid);
reverse(mid+1,r,(i<<1)+1,mid+1,rr);
}
}
long find(long l,long r,long i,long v)
{
long mid = (l+r)>>1;
if (l == r)
{
return count[i];
}
if (v < mid+1)
{
return count[i] ^ find(l,mid,i<<1,v);
}
if (v > mid)
{
return count[i] ^ find(mid+1,r,(i<<1)+1,v);
}
}
inline int getint()
{
int res = 0; char tmp; bool sgn = 1;
do tmp = getchar();
while (!isdigit(tmp) && tmp != '-');
if (tmp == '-')
{
sgn = 0;
tmp = getchar();
}
do res = (res << 1) + (res << 3) + tmp - '0';
while (isdigit(tmp = getchar()));
return sgn ? res : -res;
}
int main()
{
freopen("easy.in","r",stdin);
freopen("easy.out","w",stdout);
n = getint();
m = getint();
for (long i=1;i<m+1;i++)
{
long t;long l;long r;
t = getint();
if (t == 1)
{
l = getint();
r = getint();
if (l > r) continue;
reverse(1,n,1,l,r);
}
else
{
l = getint();
long tmp = find(1,n,1,l);
if (tmp & 1)
printf("1\n");
else
printf("0\n");
}
}
return 0;
}
树状数组
#include <string>
#include <cstdio>
#define Lowbit(x) ((x)&(-x))
long N;long m;
long c[100010];
inline void reverse(long x)
{
while (x > 0)
{
c[x] ^= 1;
x -= Lowbit(x);
}
}
inline long find(long x)
{
long ans = 0;
while (x < N+1)
{
ans ^= c[x];
x += Lowbit(x);
}
return ans;
}
inline int getint()
{
int res = 0; char tmp; bool sgn = 1;
do tmp = getchar();
while (!isdigit(tmp) && tmp != '-');
if (tmp == '-')
{
sgn = 0;
tmp = getchar();
}
do res = (res << 1) + (res << 3) + tmp - '0';
while (isdigit(tmp = getchar()));
return sgn ? res : -res;
}
int main()
{
freopen("easy.in","r",stdin);
freopen("easy.out","w",stdout);
N = getint();
m = getint();
for (long i=1;i<m+1;i++)
{
long t;long a;long b;
t = getint();
if (t == 1)
{
a = getint();
b = getint();
reverse(b);
if (a > 1)
reverse(a-1);
}
else
{
a = getint();
if (find(a) & 1)
printf("1\n");
else
printf("0\n");
}
}
return 0;
}
线段树一开始TLE的原因:这道题根本就不需要-1,这道题只需要在每个节点上记录信息,不管两个儿子的关系。
只在统计的时候一直遍历到叶节点就好。。因为这道题记录翻转次数,父亲的翻转次数和儿子的翻转次数并不矛盾,儿子的翻转次数等于自己的加上父亲的
蜥蜴
调了一下午,最后发现END打成了N。
#include <cstdio>
#define MIN(a,b) ((a)<(b)?(a):(b))
#define GETIND1(a,b) (((a-1)*(M)+(b-1))<<1)
#define GETIND2(a,b) ((((a-1)*(M)+(b-1))<<1)+1)
#define DIST(x1,y1,x2,y2) ((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1))
long N;long M;long d;
const long inf = 0x7f7f7f7f;
struct node
{
long ind;
long f;
node* nxt;
node* bck;
};
node* head[1000];
long D[1000];
long DN[1000];
long END;
long START;
long SUM;
long height[30][30];
bool hash[1000][1000];
long Sap(long u,long maxflow)
{
#ifdef Debug
if (u == START) printf("U : START:\n");
else if (u == END) printf("U : END:\n");
else
printf("U : (%ld,%ld,%ld)\n",u/2/M+1,u/2%M+1,u&1);
#endif
if (u == END)
{
return maxflow;
}
long tmp = 0;
for (node* vv=head[u];vv;vv=vv->nxt)
{
long v = vv->ind;
#ifdef Debug
if (v == START) printf("V : START:\n");
else if (v == END) printf("V : END:\n");
else
printf("V : (%ld,%ld,%ld,f:%ld)\n",v/2/M+1,v/2%M+1,v&1,vv->f);
#endif
if (D[v]+1 == D[u] && vv->f > 0)
{
long rv = Sap(v,MIN(maxflow-tmp,vv->f));
vv->f -= rv;
vv->bck->f += rv;
tmp += rv;
if (tmp == maxflow)
return tmp;
}
}
if (D[START] == SUM+1)
{
return tmp;
}
DN[D[u]] --;
if (!DN[D[u]])
D[START] = SUM+1;
DN[++D[u]]++;
return tmp;
#ifdef Debug
printf("-----------\n");
#endif
}
void insert(long a,long b,long f,long f2)
{
node* nn = new node;
nn->ind = b;
nn->f = f;
nn->nxt = head[a];
head[a] = nn;
nn = new node;
nn->ind = a;
nn->f = f2;
nn->nxt = head[b];
head[b] = nn;
head[a]->bck = head[b];
head[b]->bck = head[a];
}
int main()
{
freopen("lizard.in","r",stdin);
freopen("lizard.out","w",stdout);
scanf("%ld%ld%ld",&N,&M,&d);
START = N*M*2+10;
END = START + 1;
SUM = N*M*2+2;
for (long i=1;i<N+1;i++)
{
scanf("\n");
for (long j=1;j<M+1;j++)
{
char tmp;
scanf("%c",&tmp);
tmp -= '0';
height[i][j] = tmp;
if (tmp)
{
insert(GETIND1(i,j),GETIND2(i,j),tmp,0);
}
}
}
long SumLizard = 0;
for (long i=1;i<N+1;i++)
{
scanf("\n");
for (long j=1;j<M+1;j++)
{
char tmp;
scanf("%c",&tmp);
if (tmp == 'L')
{
SumLizard ++;
insert(START,GETIND1(i,j),1,0);
}
}
}
for (long i=1;i<N+1;i++)
{
for (long j=1;j<M+1;j++)
{
if (height[i][j])
{
for (long p=1;p<N+1;p++)
{
for (long q=1;q<M+1;q++)
{
if (height[p][q])
if ((p-i || q-j) && !hash[GETIND1(i,j)][GETIND1(p,q)])
if (DIST(i,j,p,q) <= d*d)
{
insert(GETIND2(i,j),GETIND1(p,q),inf,0);
insert(GETIND2(p,q),GETIND1(i,j),inf,0);
hash[GETIND1(i,j)][GETIND1(p,q)] =
hash[GETIND1(p,q)][GETIND1(i,j)] = true;
}
}
}
if (i<d+1 || j<d+1 || i+d>N || j+d>M)
{
insert(GETIND2(i,j),END,inf,0);
}
}
}
}
DN[0] = SUM;
long ans = 0;
while (D[START]<SUM)
{
ans += Sap(START,inf);
}
printf("%ld",SumLizard-ans);
return 0;
}
运输问题
有两个问题,必须要建反向边(费用为相反数),还有start我设为0,结果在减少流量的时候被当做不存在的点了(因为while(pp)这句),以后不要用0作源点了。
#include <cstdio>
#define MIN(a,b) ((a)<(b)?(a):(b))
long m;long n;
long end;
long start;
long dist[300];
long f[300][300];
long f2[300][300];
long que[1000];
long a[300];
long b[300];
bool vis[300];
long map[300][300];
long pre[300];
long ans = 0;
const long inf = 0x7f7f7f7f;
long ans2= 0;
bool Spfa()
{
for (long i=1;i<n+m+3;i++)
{
dist[i] = inf;
vis[i] = false;
pre[i] = 0;
}
long l = 0;
long r = 0;
que[++r] = start;
dist[start] = 0;
while (l<r)
{
long u = que[++l];
vis[u] = false;
for (long v=1;v<n+m+3;v++)
{
if (f[u][v] > 0)
{
if (dist[v]>dist[u]+map[u][v])
{
pre[v] = u;
dist[v] = dist[u]+map[u][v];
if (!vis[v])
{
vis[v] = true;
que[++r] = v;
}
}
}
}
}
return dist[end]<inf;
}
bool Spfa2()
{
long l = 0;
long r = 0;
for (long i=1;i<n+m+3;i++)
{
dist[i] = -inf;
vis[i] = false;
pre[i] = 0;
}
que[++r] = start;
dist[start] = 0;
while (l<r)
{
long u = que[++l];
vis[u] = false;
for (long v=1;v<n+m+3;v++)
{
if (f2[u][v] > 0)
{
if (dist[v]<dist[u]+map[u][v])
{
pre[v] = u;
dist[v] = dist[u]+map[u][v];
if (!vis[v])
{
vis[v] = true;
que[++r] = v;
}
}
}
}
}
return dist[end]>-inf;
}
void work()
{
while (1)
{
if (!Spfa())break;
long p = end;
long pp = pre[end];
long mincut = inf;
while (pp)
{
mincut = MIN(mincut,f[pp][p]);
p = pp;pp = pre[pp];
}
ans += dist[end]*mincut;
p = end;
pp = pre[end];
while (pp)
{
f[pp][p] -= mincut;
f[p][pp] += mincut;
p = pp;pp = pre[pp];
}
}
printf("%ld\n",ans);
while (1)
{
if (!Spfa2())break;
long p = end;
long pp = pre[end];
long mincut = inf;
while (pp)
{
mincut = MIN(mincut,f2[pp][p]);
p = pp;pp = pre[pp];
}
ans2 += dist[end]*mincut;
p = end;
pp = pre[end];
while (pp)
{
f2[pp][p] -= mincut;
f2[p][pp] += mincut;
p = pp;pp = pre[pp];
}
}
printf("%ld",ans2);
}
int main()
{
freopen("trans.in","r",stdin);
freopen("trans.out","w",stdout);
scanf("%ld%ld",&n,&m);
start = n+m+1;
end = n+m+2;
for (long i=1;i<n+1;i++)
{
scanf("%ld",a+i);
map[start][i] = 0;
f[i][start] = 0;
f[start][i] = a[i];
f2[i][start] = 0;
f2[start][i] = a[i];
}
for (long i=1;i<m+1;i++)
{
scanf("%ld",b+i+n);
map[i+n][end] = 0;
f[i+n][end] = b[i+n];
f[end][i+n] = 0;
f2[i+n][end] = b[i+n];
f2[end][i+n] = 0;
}
for (long i=1;i<n+1;i++)
{
for (long j=1;j<m+1;j++)
{
long tmp;scanf("%ld",&tmp);
map[i][j+n] = tmp;
map[j+n][i] = -tmp;
f[i][j+n] = inf;
f[j+n][i] = 0;
f2[i][j+n] = inf;
f2[j+n][i] = 0;
}
}
work();
return 0;
}
郁闷的出纳员
很长一段时间后又再次被坑了。来的时候工资就低于min的,直接离开,而且不算入总的离开人数。
这道题的delete模块想了很久,相出了这个方法,感觉还不错。如果根小于min则删除根节点和左子树,用右子树替换根,重复这个操作直到根大于min。然后递归在左儿子中删除。。。调了很久。1、因为删除了之后,忘了更新sum。2、删除之后,不能减少size,因为会把有的节点的内存覆盖了。要用size就用sum[root]表示
#include <cstdlib>
#include <cstdio>
long size = 0;
long ls[100010];
long rs[100010];
long sum[100010];
long tree[15000010];
long hr[100010];
long n;long min;long delta=0;long root = 0;
long leave = 0;
void r_rotate(long &k)
{
long tmp = ls[k];
ls[k] = rs[tmp];
rs[tmp] = k;
sum[tmp] = sum[k];
sum[k] = sum[ls[k]]+sum[rs[k]]+1;
k = tmp;
}
void l_rotata(long &k)
{
long tmp = rs[k];
rs[k] = ls[tmp];
ls[tmp] = k;
sum[tmp] = sum[k];
sum[k] = sum[ls[k]]+sum[rs[k]]+1;
k = tmp;
}
void insert(long& k,long v)
{
if (k == 0)
{
size ++;
tree[size] = v;
k = size;
sum[k] = 1;
hr[k] = long(double(rand())/RAND_MAX*100010);
return;
}
sum[k] ++;
if (v <= tree[k])
{
insert(ls[k],v);
if (hr[ls[k]] > hr[k])
{
r_rotate(k);
}
}
if (v > tree[k])
{
insert(rs[k],v);
if (hr[rs[k]] > hr[k])
{
l_rotata(k);
}
}
}
long findk(long &k,long v)
{
if (sum[ls[k]]+1 == v)
{
return tree[k];
}
else if (sum[ls[k]] >= v)
{
return findk(ls[k],v);
}
else
{
return findk(rs[k],v-sum[ls[k]]-1);
}
}
long del(long& k)
{
if (k == 0) return 0;
long delcount = 0;
while (k && tree[k]+delta<min)
{
long dec = sum[ls[k]] + 1;
delcount += dec;
leave += dec;
ls[k] = 0;
k = rs[k];
}
if (k && tree[k]+delta>=min)
{
if (ls[k])
{
long tmp = del(ls[k]);
delcount += tmp;
sum[k] -= tmp;
}
}
return delcount;
}
int main()
{
freopen("cashier.in","r",stdin);
freopen("cashier.out","w",stdout);
scanf("%ld%ld",&n,&min);
for (long i=1;i<n+1;i++)
{
char op;long opt;
scanf("\n%c",&op);
scanf("%ld",&opt);
switch(op)
{
case 'I':
if (opt >= min)
insert(root,opt-delta);
break;
case 'A':
delta+=opt;
break;
case 'S':
delta-=opt;
del(root);
break;
case 'F':
if (opt > sum[root])
printf("-1\n");
else
printf("%ld\n",findk(root,sum[root]-opt+1)+delta);
break;
}
}
printf("%ld",leave);
return 0;
}
宫廷守卫
一开始一直把左半集和右半集的计数bcnt1和bcnt2搞混。。
#include <cstring>
#include <cstdio>
struct node
{
long ind;
node* nxt;
};
node* head[10000];
bool vis[10000];
long lnk[10000];
char map[300][300];
long bcnt1 = 0;
long bcnt2 = 0;
struct Block
{
long i1;
long i2;
long j1;
long j2;
};
Block block1[10000];
Block block2[10000];
bool Hungary(long u)
{
for (node* vv=head[u];vv;vv=vv->nxt)
{
long v = vv->ind;
if (!vis[v])
{
vis[v] = true;
if (!lnk[v] || Hungary(lnk[v]))
{
lnk[v] = u;
return true;
}
}
}
return false;
}
void insert(long a,long b)
{
node* nn = new node;
nn -> ind = b;
nn -> nxt = head[a];
head[a] = nn;
}
bool Cross(Block& b1,Block& b2)
{
if (map[b1.i1][b2.j1]) return false;
if (b1.j2 < b2.j1 || b1.j1 > b2.j1) return false;
if (b2.i2 < b1.i1 || b2.i1 > b1.i1) return false;
return true;
}
int main()
{
freopen("guards.in","r",stdin);
freopen("guards.out","w",stdout);
long n;long m;
scanf("%ld%ld",&n,&m);
for (long i=1;i<n+1;i++)
for (long j=1;j<m+1;j++)
{
char tmp = getchar();
while (tmp == '\n' || tmp == ' ')
tmp = getchar();
map[i][j] = tmp-'0';
}
for (long i=1;i<n+1;i++)
for (long j=1;j<m+1;j++)
{
long jj = j;
if (map[i][j]-2)
{
while (map[i][jj+1]-2&&jj+1<m+1) jj++;
bcnt1 ++;
block1[bcnt1].i1 = i;
block1[bcnt1].i2 = i;
block1[bcnt1].j1 = j;
block1[bcnt1].j2 = jj;
}
j = jj;
}
for (long j=1;j<m+1;j++)
for (long i=1;i<n+1;i++)
{
long ii = i;
if (map[i][j]-2)
{
while (map[ii+1][j]-2&&ii+1<n+1) ii++;
bcnt2 ++;
block2[bcnt2].i1 = i;
block2[bcnt2].i2 = ii;
block2[bcnt2].j1 = j;
block2[bcnt2].j2 = j;
}
i = ii;
}
for (long i=1;i<bcnt1+1;i++)
for (long j=1;j<bcnt2+1;j++)
if (Cross(block1[i],block2[j]))
insert(j,i);
long ans = 0;
for (long i=1;i<bcnt2+1;i++)
{
memset(vis,0,sizeof vis);
if (Hungary(i)) ans++;
}
printf("%ld\n",ans);
for (long i=1;i<bcnt1+1;i++)
{
if (lnk[i])
printf("%ld %ld\n",block1[i].i1,block2[lnk[i]].j1);
}
return 0;
}
广场铺砖
仍然没有一次性AC
错误:
1、f的第二维下标写成了状态而不是状态的编号。
2、最后输出的时候直接输出f[ths][get_ID(0)]就好了,我还枚举了一遍。
3、now = last-(pn1<<p1)-(pn2<<p2)。我写成了now=last-pn1-pn2;
4、p1 = h-j。p2 = p1+1。我写成了p1=j-1,p2=j。忘了原来二进制数中的顺序和枚举顺序是反的,必须颠倒一下。
5、j=1的时候我直接就>>=1了。但是其实最后一个轮廓是不能有插头的。。这种要直接continue
#include <cstdio>
#include <iostream>
#include <cmath>
#include <vector>
#include <map>
#include <set>
#include <cstdlib>
typedef long long ll;
long w;long h;
long ths = 1;
long pre = 0;
long hash[4194314];
long Sta[2][4194314];
ll f[2][4194314];
long cnt[2];
long getID(long j)
{
if (!hash[j])
{
f[ths][++cnt[ths]] = 0;
hash[j] = cnt[ths];
Sta[ths][cnt[ths]] = j;
}
return hash[j];
}
void clear()
{
cnt[ths] = 0;
memset(hash,0,sizeof hash);
}
void work()
{
f[ths][getID(0)] = 1;
for (long i=1;i<w+1;i++)
{
for (long j=1;j<h+1;j++)
{
ths^=pre;pre^=ths;ths^=pre;
clear();
for (long k=1;k<cnt[pre]+1;k++)
{
long last = Sta[pre][k];
if (j == 1)
{
if (!(last&1))
last >>= 1;
else continue;
}
long p1 = h-j;
long p2 = p1+1;
long pn1 = (last>>p1)&1;
long pn2 = (last>>p2)&1;
long now = last-(pn1<<p1)-(pn2<<p2);
if (!pn1 && !pn2)
{
f[ths][getID(now|(1<<p2))] += f[pre][k];
f[ths][getID(now|(1<<p1))] += f[pre][k];
}
else if (!pn1 || !pn2)
{
f[ths][getID(now)] += f[pre][k];
}
}
}
}
std::cout << f[ths][getID(0)];
}
int main()
{
freopen("floor.in","r",stdin);
freopen("floor.out","w",stdout);
scanf("%ld%ld",&w,&h);
work();
return 0;
}
函数依赖。
才知道有strcmp这个函数。可以直接用到qsort的比较程序里,强制转换一下就行了。
不过必须字符串是0下标开始才行
#include <algorithm>
#include <cstdio>
char tmp[1100];
long from[1100];
long to[110];
char num[1500][110];
char ans2[1500][110];
long ans[1500];
bool hash[1500];
long cnt = 0;
void translate(long u)
{
long tmp = ans[u];
char tmp2[30] = "";
long pos = 0;
do
{ pos ++;
if (tmp & 1)
tmp2[pos] = true;
}while (tmp>>=1);
pos = -1;
for (long i=1;i<27;i++)
{
if (tmp2[i])
ans2[u][++pos] = 'A'+i-1;
}
}
int cmp(const void *a, const void *b)
{
return strcmp((char *)a, (char *)b);
}
#ifdef Debug
bool PAUSE=false;
#endif
int main()
{
freopen("dependence.in","r",stdin);
freopen("dependence.out","w",stdout);
long n;long m;
scanf("%ld%ld",&n,&m);
for (long i=1;i<m+1;i++)
{
#ifdef Debug
if (i == 91)
{
PAUSE = true;
}
#endif
scanf("%s",tmp+1);
long pos = 0;
while (tmp[++pos]-'-')
from[i] |= (1<<(tmp[pos]-'A'));
pos ++;
while (tmp[++pos])
to[i] |= (1<<(tmp[pos]-'A'));
}
for (long S=1;S<(1<<n);S++)
{
bool flag = false;
long s = S;
for (long i=1;i<cnt+1;i++)
{
if ((ans[i]|S)==S)
{
flag = true;
break;
}
}
if (flag) continue;
while (1)
{
bool ok = false;
for (long i=1;i<m+1;i++)
{
if ((s|from[i])==s && (s|to[i])-s)
{
#ifdef Debug
if (S == 389)
{
PAUSE = true;
}
#endif
s|=to[i];
ok = true;
}
}
if (!ok) break;
if (s==(1<<n)-1)
ans[++cnt] = S;
#ifdef Debug
if (ans[cnt] == 389)
{
PAUSE = true;
}
#endif
}
}
if (cnt)
{
printf("%ld\n",cnt);
for (long i=1;i<cnt+1;i++)
translate(i);
qsort(ans2+1,cnt,sizeof ans2[0],(int(*)(const void*, const void *))cmp);
for (long i=1;i<cnt+1;i++)
printf("%s\n",ans2[i]);
}
else printf("No candidate key");
return 0;
}
宠物收养所。
第二次打。打错了两个地方。
1、_del模块二分的时候没有写返回值
2、前驱和后继的preans和nxtans的初值写反了。preans是要找最大的,nxtans是要找最小的
#include <cmath>
#include <cstring>
#include <string>
#include <map>
#include <vector>
#include <algorithm>
#include <iostream>
#include <cstdio>
const long inf = 0x7f7f7f7f;
const long MS = 80010;
long ABS(long a)
{
return a>0?a:-a;
}
struct Treap
{
long tree[MS];
long hr[MS];
long ls[MS];
long rs[MS];
long sum[MS];
long root;
long top;
long preans;
long nxtans;
Treap():root(0),top(0)
{
memset(tree,0,sizeof tree);
memset(ls,0,sizeof ls);
memset(rs,0,sizeof rs);
memset(sum,0,sizeof sum);
}
void l_rotate(long& k)
{
long tmp = rs[k];
rs[k] = ls[tmp];
ls[tmp] = k;
sum[tmp] = sum[k];
sum[k] = sum[ls[k]]+sum[rs[k]];
k = tmp;
}
void r_rotate(long& k)
{
long tmp = ls[k];
ls[k] = rs[tmp];
rs[tmp] = k;
sum[tmp] = sum[k];
sum[k] = sum[ls[k]]+sum[rs[k]];
k = tmp;
}
void _insert(long& k,long v)
{
if (!k)
{
top ++;
sum[top] = 1;
hr[top] = rand();
tree[top] = v;
k = top;
return;
}
sum[k] ++;
if (v <= tree[k])
{
_insert(ls[k],v);
if (hr[ls[k]]<hr[k])
{
r_rotate(k);
}
}
else
{
_insert(rs[k],v);
if (hr[rs[k]]<hr[k])
{
l_rotate(k);
}
}
}
long _del(long& k,long v)
{
sum[k] --;
if (tree[k]==v || (!ls[k]&&v<tree[k]) || (!rs[k]&&v>tree[k]))
{
long tmp = tree[k];
if (!ls[k] || !rs[k])
{
k = ls[k] + rs[k];
return tmp;
}
tree[k] = _del(ls[k],v+1);
return tmp;
}
if (v <= tree[k])
return _del(ls[k],v);
if (v > tree[k])
return _del(rs[k],v);
}
void _pre(long& k,long v)
{
if (!k) return;
if (tree[k]<=v && tree[k]>preans)
preans = tree[k];
if (v <= tree[k])
_pre(ls[k],v);
if (v > tree[k])
_pre(rs[k],v);
}
void _nxt(long& k,long v)
{
if (!k) return;
if (tree[k]>=v && tree[k]<nxtans)
nxtans = tree[k];
if (v <= tree[k])
_nxt(ls[k],v);
if (v > tree[k])
_nxt(rs[k],v);
}
long pre(long v){preans=-inf;_pre(root,v);if(preans+inf)return preans;return -1;}
long nxt(long v){nxtans=inf;_nxt(root,v);if(nxtans-inf)return nxtans;return -1;}
void insert(long v){_insert(root,v);}
long del(long v){long tmp=_del(root,v);if(tmp-v){_insert(root,tmp);return -1;}return v;}
};
long getint()
{
long rs=0;char tmp;bool sgn=1;
do tmp = getchar();
while (!isdigit(tmp)&&tmp-'-');
if (tmp=='-'){tmp=getchar();sgn=0;}
do rs=(rs<<3)+(rs<<1)+tmp-'0';
while (isdigit(tmp=getchar()));
return sgn?rs:-rs;
}
Treap pet;
Treap man;
int main()
{
freopen("pet.in","r",stdin);
freopen("pet.out","w",stdout);
long n = getint();
long ans = 0;
for (long i=1;i<n+1;i++)
{
long a = getint();
long b = getint();
if (a)//MAN
{
long pre = pet.pre(b);
long nxt = pet.nxt(b);
long minc = inf;
long chos = -1;
if (pre+1)
{
if (minc > ABS(pre-b))
{
minc = ABS(pre-b);
chos = pre;
}
}
if (nxt+1)
{
if (minc > ABS(nxt-b))
{
minc = ABS(nxt-b);
chos = nxt;
}
}
if (chos + 1)
{
pet.del(chos);
ans = (ans%1000000 + minc%1000000)%1000000;
}
else
{
man.insert(b);
}
}
else
{
long pre = man.pre(b);
long nxt = man.nxt(b);
long minc = inf;
long chos = -1;
if (pre+1)
{
if (minc > ABS(pre-b))
{
minc = ABS(pre-b);
chos = pre;
}
}
if (nxt+1)
{
if (minc > ABS(nxt-b))
{
minc = ABS(nxt-b);
chos = nxt;
}
}
if (chos + 1)
{
man.del(chos);
ans = (ans%1000000 + minc%1000000)%1000000;
}
else
{
pet.insert(b);
}
}
}
std::cout << ans;
return 0;
}
报表统计
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <iostream>
#include <map>
#include <set>
const long MS = 5000010;
const long inf = 0x7f7f7f7f;
long num[MS][2];
char tmp;
long min_sort_gap = inf;
#define ABS(a) ((a)>0?(a):-(a))
#define MIN(a,b) ((a)<(b)?(a):(b))
struct Treap
{
long tree[MS];
long hr[MS];
long ls[MS];
long rs[MS];
long sum[MS];
long top;
long root;
long preans;
long nxtans;
Treap():top(0),root(0)
{
memset(sum,0,sizeof sum);
memset(tree,0,sizeof tree);
memset(ls,0,sizeof ls);
memset(rs,0,sizeof rs);
}
void l_rotate(long& k)
{
long tmp = rs[k];
rs[k] = ls[tmp];
ls[tmp] = k;
sum[tmp] = sum[k];
sum[k] = sum[ls[k]]+sum[rs[k]]+1;
k = tmp;
}
void r_rotate(long& k)
{
long tmp = ls[k];
ls[k] = rs[tmp];
rs[tmp] = k;
sum[tmp] = sum[k];
sum[k] = sum[ls[k]]+sum[rs[k]]+1;
k = tmp;
}
void _insert(long& k ,long v)
{
if (!k)
{
top ++;
sum[top] = 1;
tree[top] = v;
hr[top] = rand();
k = top;
return;
}
sum[k]++;
if (v <= tree[k])
{
_insert(ls[k],v);
if (hr[ls[k]]>hr[k])
{
r_rotate(k);
}
}
else if (v > tree[k])
{
_insert(rs[k],v);
if (hr[rs[k]]>hr[k])
{
l_rotate(k);
}
}
}
long _del(long &k,long v)
{
if (!k) return v;
sum[k] --;
if (tree[k]==v || v<tree[k]&&!ls[k] || v>tree[k]&&!rs[k])
{
long tmp = tree[k];
if (!ls[k] || !rs[k])
{
k = ls[k] + rs[k];
return tmp;
}
tree[k] = _del(ls[k],v+1);
return tmp;
}
if (v <= tree[k])
return _del(ls[k],v);
else if (v > tree[k])
return _del(rs[k],v);
}
void _pre(long& k,long v)
{
if (!k) return;
if (tree[k]<=v && tree[k]>preans)
preans = tree[k];
if (v <= tree[k])
_pre(ls[k],v);
if (v > tree[k])
_pre(rs[k],v);
}
void _nxt(long& k,long v)
{
if (!k) return;
if (tree[k]>=v && tree[k]<nxtans)
nxtans = tree[k];
if (v <= tree[k])
_nxt(ls[k],v);
if (v > tree[k])
_nxt(rs[k],v);
}
long _first(long &k)
{
if (!ls[k]) return tree[k];
return _first(ls[k]);
}
long pre(long v){preans=-inf;_pre(root,v);if(preans==-inf){return -1;}return preans;}
long nxt(long v){nxtans=inf;_nxt(root,v);if(nxtans==inf){return -1;}return nxtans;}
long del(long v){long tmp=_del(root,v);if(tmp-v){_insert(root,tmp);return -1;}return v;}
void insert(long v){_insert(root,v);}
long first(){return _first(root);}
};
Treap storage;
Treap mingap;
long size[MS];
long getint()
{
long rs=0;char tmp;bool sgn=1;
do tmp = getchar();
while (!isdigit(tmp)&&tmp-'-');
if (tmp=='-'){tmp=getchar();sgn=0;}
do rs=(rs<<3)+(rs<<1)+tmp-'0';
while (isdigit(tmp=getchar()));
return sgn?rs:-rs;
}
int main()
{
freopen("form.in","r",stdin);
freopen("form.out","w",stdout);
long n;long m;
n = getint();
m = getint();
for (long i=1;i<n+1;i++)
{
num[i][0] = getint();
if (i > 1)
{
mingap.insert(ABS(num[i][0]-num[i-1][0]));
long pre = storage.pre(num[i][0]);
long nxt = storage.nxt(num[i][0]);
if (pre+1)
min_sort_gap = MIN(min_sort_gap,ABS(num[i][0]-pre));
if (nxt+1)
min_sort_gap = MIN(min_sort_gap,ABS(num[i][0]-nxt));
}
size[i] = 1;
storage.insert(num[i][0]);
}
while (m--)
{
do tmp = getchar();
while (tmp-'I'&&tmp-'M');
if (tmp == 'I')
{
long a;long b;
a = getint();
b = getint();
if (size[a] > 1)
{
if (a < n)
mingap.del(ABS(num[a][1]-num[a+1][0]));
mingap.insert(ABS(num[a][1]-b));
}
else
{
if (a < n)
mingap.del(ABS(num[a][0]-num[a+1][0]));
mingap.insert(ABS(num[a][0]-b));
}
if (a < n)
mingap.insert(ABS(num[a+1][0]-b));
num[a][1] = b;
if (min_sort_gap)
{
long pre = storage.pre(b);
long nxt = storage.nxt(b);
if (pre+1)
min_sort_gap = MIN(min_sort_gap,ABS(pre-b));
if (nxt+1)
min_sort_gap = MIN(min_sort_gap,ABS(nxt-b));
storage.insert(b);
}
size[a] = 2;
}
else
{
do tmp = getchar();
while (tmp-'S'&&tmp-'G');
if (tmp == 'S')
printf("%ld\n",min_sort_gap);
else
printf("%ld\n",mingap.first());
}
}
return 0;
}