求助大佬

P4119 [Ynoi2018] 未来日记

> 这个比较漂亮 ```cpp #include <cstdio> #define Lowbit(x) ((x) & -(x)) #define border 50001 #define inc(a) ++a using namespace std; int place[50001][50],num[51000][6],copy1[51000][6],copy2[51000][6],ans[51000],a[51000]; int tree[880000]; int n,m,l,r,x,y,k,cnt,ques,order; void read() { int ret=0,f=1; char ch=getchar(); while (ch<'0'||ch>'9') {if (ch=='-') f=-f;ch=getchar();} while (ch>='0'&&ch<='9') ret=ret*10+ch-'0',ch=getchar(); return ret*f; } int Query(int x){ if (x<=0) return 0; int sum=0; for(;x;x-=Lowbit(x)) sum+=tree[x]; return sum; } void Insert(int x,int k){ if (x<=0) return; for(;x<=n;x+=Lowbit(x)) tree[x]+=k; } void Divid(int l,int r,int left,int right){ if (l>r or left>right) return; if (l==r) { for(int i=left;i<=right;i++) if (num[i][5]==1) ans[num[i][4]]=l; return; } int mid=(l+r) >> 1,tot[2]; tot[1]=0; tot[2]=0; for(int i=left;i<=right;inc(i)){ if (num[i][5]==1){ int tmp=Query(num[i][2])-Query(num[i][1]-1); if (tmp>=num[i][3]){ inc(tot[1]); for(int j=1;j<=5;inc(j)) copy1[tot[1]][j]=num[i][j]; } else { num[i][3]-=tmp; inc(tot[2]); for(int j=1;j<=5;inc(j)) copy2[tot[2]][j]=num[i][j]; } } else { if (num[i][1]<=mid){ inc(tot[1]); for(int j=1;j<=5;inc(j)) copy1[tot[1]][j]=num[i][j]; Insert(num[i][4],num[i][2]); } else { inc(tot[2]); for(int j=1;j<=5;inc(j)) copy2[tot[2]][j]=num[i][j]; } } } for(int i=1;i<=tot[1];inc(i)) if (copy1[i][5]==0) Insert(copy1[i][4],-copy1[i][2]); for(int i=1;i<=tot[1];inc(i)) for(int j=1;j<=5;inc(j)) num[left+i-1][j]=copy1[i][j]; for(int i=1;i<=tot[2];inc(i)) for(int j=1;j<=5;inc(j)) num[left+tot[1]+i-1][j]=copy2[i][j]; Divid(l,mid,left,left+tot[1]-1); Divid(mid+1,r,left+tot[1],right); } int main(){ n:=read(); m:=read(); ques=0; for(int i=1;i<=n;inc(i)){ a[i]:=read(); inc(place[a[i]][0]); place[a[i]][place[a[i]][0]]=i; inc(cnt); num[cnt][1]=a[i]; num[cnt][2]=1; num[cnt][4]=i; } for(int i=1;i<=m;inc(i)){ order:=read(); if (order==2){ l:=read(); r:=read(); k:=read(); inc(ques); inc(cnt); num[cnt][1]=l; num[cnt][2]=r; num[cnt][3]=k; num[cnt][4]=ques; num[cnt][5]=1; } if (order==1){ l:=read(); r:=read(); x:=read(); y:=read(); for(int j=1;j<=place[x][0];inc(j)) if (place[x][j]>=l and place[x][j]<=r){ inc(cnt); num[cnt][1]=x; num[cnt][2]=-1; num[cnt][4]=place[x][j]; inc(cnt); num[cnt][1]=y; num[cnt][2]= 1; num[cnt][4]=place[x][j]; a[place[x][j]]=y; inc(place[y][0]); place[y][place[y][0]]=place[x][j]; place[x][j]=-1; } } printf("%d %d\n",i,cnt); } //for(int i=1;i<=cnt;inc(i)) printf("%d %d %d %d %d %d\n",i,num[i][1],num[i][2],num[i][3],num[i][4],num[i][5]); //printf("%d \n",cnt); for(int i=1;i<=cnt;inc(i)) printf("%d %d",num[i][1],num[i][2]); /*Divid(0,border,1,cnt); for(int i=1;i<=ques;inc(i)) printf("%d\n",ans[i]);*/ return 0; } ```
by arfa @ 2018-12-12 13:27:06


> 还是看第一个,下面那个编错
by arfa @ 2018-12-12 13:35:00


这题有log解法的吗? 惊了惊了
by shadowice1984 @ 2018-12-12 13:55:03


> @[shadowice1984](/space/show?uid=56384) 不是啊,如果数据不随机就不行。在数据随机的情况下,每一个数字的出现次数均为 $\frac{N}{num}$ 也就是 $1$,所以每一次修改只需要存储下来,次数约为 $1$(玄学复杂度)。然后我们考虑单点修改,区间查询第 $K$ 大可以用整体二分。时间复杂度为 $O((M\times $玄学$+N \log^2 num))$。如果不随机那就变成 $O((M+N^2) \log^2 num)$ 了,不过看来数据还是不随机的。
by arfa @ 2018-12-12 17:35:31


@[arfa](/space/show?uid=77760) ynoi不可能有随机数据
by shadowice1984 @ 2018-12-12 18:57:38


别天天想着随机数据过题 ODT这种东西让我见识到了随机数据的脆弱
by noip @ 2019-02-16 13:26:18



by 许多 @ 2022-07-16 17:54:09


|