我看不少人和我一样,这样写会过60%其他TLE,好像是卡常或者别的什么? 不过思路已经确定了,下面这串仅供参考
#define int long long
using namespace std;
//修补骑士之前写过树状数组,加权线段树,以及归并排序的方法
//对于树状数组与线段树,都是利用logn的特效,用nlogn的特性暴力过了
//对于2e6的数据,肯定是会超时的
//由于我们想求的只是奇偶性,所以说肯定在奇偶性上有优化点,就是我还不知道是什么
//TK之前也在想只对于转化的区间有变化,前面与后面实际上顺序都无所谓,不过由于“区间”的变化很难搞,就。。。。
//我们假设原来有y个逆序对,区间内原有j个逆序对,有h个元素,则总对数是(n - 1)n/2
//则逆序对变成了((n - 1)n - 2j)/2,也就是y - 2j + (n - 1)n/2
//j就一直是偶数,就可以不用管了!专心于y与n!
int calnum(int n)
{
return (n - 1) * n / 2;
}
int lowbit(int x)
{
return x & -x;
}
void change(int pos,int du,int n,vector<int> &tree)
{
for(;pos <= n;pos += lowbit(pos))//不停向上走说是
{
tree[pos] += du;
}
}
int sum(int pos,vector<int> &tree)
{
int ans = 0;
for(;pos > 0;pos -= lowbit(pos))
{
ans += tree[pos];
}
return ans;
}
signed main()
{
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n;
cin>>n;
vector<int> num(n,0);
for(int r = 0;r < n;r++)
{
cin>>num[r];
}
int maxnum = *max_element(num.begin(),num.end());
vector<int> tree(maxnum + 7,0);//排列与序列搞混了,奇异搞笑
int m;
cin>>m;
//之后计算原本逆序对
int orig = 0;
int front = 0;
for(int r = 0;r < n;r++)
{
orig += front - sum(num[r],tree);//不包含自己(还没进去)所有不大于自己的元素
front++;
change(num[r],1,maxnum,tree);
}
for(int w = 0;w < m;w++)
{
int l,r;
cin>>l>>r;
int n = r - l + 1;
int judge = calnum(n);
orig += judge;
if(orig % 2 == 0)
{
orig = 2;
cout<<"like"<<endl;
}
else
{
orig = 1;
cout<<"dislike"<<endl;
}
}
return 0;
}
我这里是树状数组解决的,你用线段树,归并排序之类看自己心情。传送门这里有更加详细的逆序对说明
这样会TLE,有点恶心人说是 而且好像还不止我一个人有这种问题,不痛不痒的修改之后就可以AC了
using namespace std;
inline int read()
{
int x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9')
{
if (ch == '-')
{
f = -1;
}
ch = getchar();
}
while(ch >= '0' && ch <= '9')
{
x = (x<<1) + (x<<3) + (ch^48);
ch = getchar();
}
return x * f;
}
int calnum(int n)
{
return (n - 1) * n / 2;
}
int lowbit(int x)
{
return x & -x;
}
void change(int pos,int du,int n,vector<int> &tree)
{
for(;pos <= n;pos += lowbit(pos))
{
tree[pos] += du;
}
}
int sum(int pos,vector<int> &tree)
{
int ans = 0;
for(;pos > 0;pos -= lowbit(pos))
{
ans += tree[pos];
}
return ans;
}
signed main()
{
int n;
n = read();
vector<int> num(n,0);
for(int r = 0;r < n;r++)
{
num[r] = read();
}
int maxnum = *max_element(num.begin(),num.end());
vector<int> tree(maxnum + 7,0);
int m;
cin>>m;
long long orig = 0;
int front = 0;
for(int r = 0;r < n;r++)
{
orig += front - sum(num[r],tree);
front++;
change(num[r],1,maxnum,tree);
}
for(int w = 0;w < m;w++)
{
int l,r;
l = read();
r = read();
int n = r - l + 1;
int judge = calnum(n);
orig += judge;
if(orig % 2 == 0)
{
orig = 2;
printf("like\n");
}
else
{
orig = 1;
printf("dislike\n");
}
}
return 0;
}
这里的修改还是经典卡常老三样
1:把cout给换成printf,endl换成\n。原理我说不清楚,大家可以去找视频看看
2:使用read(),这个也是板子,要用了直接复制粘贴就OK了
3:去掉define int long long “别(两个字母)define int long long了”————jiangly