今天做学习总结,发现好几道以前积压的题目,应该都是思路正确但是代码调不出来的,求助各位大佬!
正常思路,样例过了,但是我写的可持久化线段树好像和主流的不太一样,没看过板子,自己憋出来的。常数略大,需开O2。
32分代码如下:
#include<iostream>
#include<cstdio>
using namespace std;
struct node {
int l,r,v,lc,rc;
} t[(int)25e6];
int top;
int root[(int)1e6+5];
int& newnode(int&u) {//newnode
return u=top++;
}
void build(int&u,int l,int r) {
t[newnode(u)]={l,r,0};
if(l==r) return;
int mid=l+r>>1;
build(t[u].lc,l,mid);
build(t[u].rc,mid+1,r);
}
void push(int h/*history*/,int u,int p,int v) {
t[u]=t[h];
if(t[u].l==t[u].r&&t[u].r==p) {t[u].v=v;return;}
int mid=t[u].l+t[u].r>>1;
if(p<=mid) push(t[h].lc,h==u?t[h].lc:newnode(t[u].lc),p,v);
if(p>mid) push(t[h].rc,h==u?t[h].rc:newnode(t[u].rc),p,v);
}
int find(int u,int p) {
if(t[u].l==t[u].r&&t[u].r==p) return t[u].v;
int mid=t[u].l+t[u].r>>1;
if(p<=mid) return find(t[u].lc,p);
if(p>mid) return find(t[u].rc,p);
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
int n,m;
cin>>n>>m;
build(root[0],1,n);
for(int i=1;i<=n;i++) {
int v;
cin>>v;
push(root[0],root[0],i,v);
}
for(int i=1;i<=m;i++) {
int a,b,c,d;
cin>>a>>b>>c;
if(b==1) {
cin>>d;
push(a,newnode(root[i]),c,d);
}
else {
// cout<<"***";
cout<<find(root[a],c)<<endl;
t[newnode(root[i])]=t[root[a]];
}
}
return 0;
}
分块,正常思路,样例已过。
0分代码如下:
#include<iostream>
#include<algorithm>
#include<climits>
#include<cmath>
using namespace std;
int block[205];
int a[40005],ap[40005],b[40005];
int t[205][40005];
int T[40005];
int pre[205][40005];
//pre[i][j]表示前i个块里大小为j的数字出现的个数之和
int k;
int n,m;
int block_l(int x) {//O(1)
return 1+(x-1)*k;
}
int block_r(int x) {//O(1)
return x*k;
}
void disc() {//O(nlogn)
for(int i=1; i<=n; i++)
ap[i]=a[i];
sort(ap+1,ap+1+n);
int end=unique(ap+1 ,ap+1+n)-ap;
for(int i=1; i<=n; i++)
b[i]=lower_bound(ap+1,ap+end,a[i])-ap;
}
int gb(int x) {//O(1)
return (x+k-1)/k;
}
void push_up(int x,int v) {//O(1)
int y=gb(x);
if(t[y][block[y]]<t[y][v]||(t[y][block[y]]==t[y][v]&&block[y]>v))
block[y]=v;
}
void push(int x,int v) {//O(1)
t[gb(x)][v]++;
push_up(x,v);
}
void make_pre() {//O(n*sqrt n)
for(int i=1; i<=gb(n); i++)
for(int j=1; j<=40000; j++)
pre[i][j]=pre[i-1][j]+t[i][j];
}
void change(int i,int lb,int rb) {
if(!T[b[i]])
T[b[i]]+=pre[rb][b[i]]-pre[lb-1][b[i]]+1;
else
T[b[i]]++;
}
int find(int l,int r) {//O(sqrt n)
if(l>r)
swap(l,r);
int maxx=1;
if(r-l+1<(k<<1)) {
//暴力
for(int i=l;i<=r;i++)
T[b[i]]++;
for(int i=l;i<=r;i++)
if(T[maxx]<T[b[i]]||(T[maxx]==T[b[i]]&&maxx>b[i]))
maxx=b[i];
for(int i=l;i<=r;i++)
T[b[i]]=0;
} else {
for(int i=l;i<=block_r(gb(l));i++)
change(i,gb(l)+1,gb(r)-1);
for(int i=block_l(gb(r));i<=r;i++)
change(i,gb(l)+1,gb(r)-1);
for(int i=gb(l)+1;i<=gb(r)-1;i++)
if(!T[block[i]])
T[block[i]]+=pre[gb(r)-1][block[i]]-pre[gb(l)+1-1][block[i]];
for(int i=l;i<=block_r(gb(l));i++)
if(T[maxx]<T[b[i]]||(T[maxx]==T[b[i]]&&maxx>b[i]))
maxx=b[i];
for(int i=block_l(gb(r));i<=r;i++)
if(T[maxx]<T[b[i]]||(T[maxx]==T[b[i]]&&maxx>b[i]))
maxx=b[i];
for(int i=l;i<=block_r(gb(l));i++)
T[b[i]]=0;
for(int i=block_l(gb(r));i<=r;i++)
T[b[i]]=0;
for(int i=gb(l)+1;i<=gb(r)-1;i++)
T[block[i]]=0;
}
return maxx;
}
int main() {
cin>>n>>m;
k=sqrt(n);
for(int i=1; i<=n; i++)
cin>>a[i];
disc();
for(int i=1; i<=n; i++)
push(i,b[i]);
make_pre();
int x=0,l,r;
while(m--) {
cin>>l>>r;
// cout<<"***";
cout<<(x=ap[find((l+x-1)%n+1,(r+x-1)%n+1)])<<endl;
}
return 0;
}
P3052 [USACO12MAR]Cows in a Skyscraper G
状压DP,设f[i]表示i情况下的最小分组数量。
16分代码如下:
#include<iostream>
#include<climits>
using namespace std;
long long f[(long long)1<<19];
long long s[(long long)1<<19];
long long a[20],n,w;
long long sigma(long long x) {
long long sum=0;
int c=1;
while(x) {
if(x&1) sum+=a[c];
c++;
x>>=1;
}
return sum;
}
int main() {
for(auto&i:f)
i=1e10;
cin>>n>>w;
for(int i=1; i<=n; i++) cin>>a[i];
for(int i=1; i<(1<<n); i++)
if((s[i]=sigma(i))<=w)
f[i]=1;
for(long long i=1; i<(1<<n); i++)
for(long long k=0; k<=n; k++) {
if(!((i>>k)&1)) continue;
long long j=i^(1<<k);
if(s[i]+s[1<<k]>w)
f[i]=min(f[i],f[j]+f[i-j]);
else
f[i]=min(f[i],f[j]+1);
}
cout<<f[(1<<n)-1];
return 0;
}
P3017 [USACO11MAR]Brownie Slicing G
二分答案,正常思路。
10分代码如下:
#include<iostream>
using namespace std;
int a[505][505],pre[505][505];
int x,y,n,m;
inline int sum(int X1,int Y1,int X2,int Y2) {
return pre[X2][Y2]-pre[X2][Y1-1]-pre[X1-1][Y2]+pre[X1-1][Y1-1];
}
bool judge_line(int X1,int X2,int K) {
int cy=1;
for(int i=1; i<m; i++) {
int j=i;
while(j<=m&&sum(X1,i,X2,j)<K)
j++;
i=j;
if(++cy==y) {
bool t=i<m?sum(X1,i+1,X2,m)>=K:true;
// if(t)
// cout<<"line "<<X1<<"~"<<X2<<" dis in "<<j<<'\n';
return t;
}
}
return false;
}
bool judge(int K) {
// cout<<"judge in K="<<K<<endl;
int cx=1;
for(int i=1; i<n; i++) {
int j=i;
while(j<=n&&!(judge_line(i,j,K)))
j++;
i=j;
if(++cx==x)
return i<n?judge_line(i+1,n,K):true;
}
return false;
}
int main() {
cin>>n>>m>>x>>y;
for(int i=1; i<=n; i++)
for(int j=1; j<=m; j++)
cin>>a[i][j];
for(int i=1; i<=n; i++)
for(int j=1; j<=m; j++)
pre[i][j]=pre[i][j-1]+pre[i-1][j]-pre[i-1][j-1]+a[i][j];
int l=0,r=pre[n][m]/(x*y);
int mid=l+r+1>>1;
while(l<r)
if(judge(mid=l+r+1>>1))
l=mid;
else
r=mid-1;
cout<<l;
return 0;
}