1. 程式人生 > >hdu 6058 連結串列 列舉

hdu 6058 連結串列 列舉

考慮每個數的貢獻,即滿足區間第k大為該數的區間個數。其實就是對於兩邊比起大的數,兩邊卡出比該數大的個數為k - 1.
用連結串列維護,考慮從小到大列舉,列舉完成後刪除該點,保證每次列舉連結串列中都是比其大的數。
O(n*k)

寫的挫

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int MAXN = 5e5 + 10;
typedef long long ll;
struct Node
{
	int next, pre;
	int pos;
	Node(){
		next = -1;
		pre = -1;
	}
}ls[MAXN];
int n, a[MAXN], k;
void init()
{
	for (int i = 0; i < MAXN; i++){
		ls[i].pre = ls[i].next = -1;
	}
}
int main()
{
	int T;
	scanf("%d", &T);
	while (T--){
		init();
		scanf("%d%d", &n, &k);
		a[0] = 0;
		a[n + 1] = n + 1;
		for (int i = 1; i <= n; i++){
			scanf("%d", &a[i]);
		}
		for (int i = 1; i <= n; i++){
			ls[a[i]].pre = a[i - 1];
			ls[a[i]].next = a[i + 1];
			ls[a[i]].pos = i;
		}
		ls[0].next = a[1];
		ls[0].pos = 0;
		ls[n + 1].pos = n + 1;
		ls[n + 1].pre = a[n];
		ll ans = 0;
		for (int i = 1; i <= n; i++){
			int low = i;
			int left = 0;
			while (true){
				if (left == k)break;
				if (low == 0)break;
				low = ls[low].pre;
				left++;
			}
			int right = 0;
			int up = i;
			while (true){
				if (right == k - left)break;
				if (up == n + 1)break;
				up = ls[up].next;
				right++;
			}
			while (low != i&&up != n + 1){		//滑動
				ans += (ll)(ls[ls[low].next].pos - ls[low].pos )
					*(ll)(ls[ls[up].next].pos - ls[up].pos) * (ll)i;
				low = ls[low].next;
				up = ls[up].next;
			}
			ls[ls[i].next].pre = ls[i].pre;		//刪點
			ls[ls[i].pre].next = ls[i].next; 
		}
		printf("%lld\n", ans);
	}
	return 0;
}


相關推薦

hdu 6058 連結串列 列舉

考慮每個數的貢獻,即滿足區間第k大為該數的區間個數。其實就是對於兩邊比起大的數,兩邊卡出比該數大的個數為k - 1. 用連結串列維護,考慮從小到大列舉,列舉完成後刪除該點,保證每次列舉連結串列中都是比

hdu 6058 連結串列

傳送門 Kanade's sum Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 1135    Accep

HDU 6215 Brute Force Sorting(雙向連結串列+佇列)

Brute Force Sorting Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) Total Submission(s): 2304    Acce

統計難題 HDU - 1251 -字典樹-連結串列實現

統計難題  HDU - 1251  題意:輸入資料的第一部分是一張單詞表,每行一個單詞,單詞的長度不超過10,它們代表的是老師交給Ignatius統計的單詞 ,一個空行代表單詞表的結束.第二部分是一連串的提問,每行一個提問,每個提問都是一個字串

【菜鳥進階】連結串列_C 結構體 共用體 列舉_遞推遞迴

座右銘 這些年我一直提醒自己一件事情,千萬不要自己感動自己。大部分人看似的努力,不過是愚蠢導致的。什麼熬夜看書到天亮,連續幾天只睡幾小時,多久沒放假了,如果這些東西也值得誇耀,那麼富士康流水線上任何一個人都比你努力多了。人難免天生有自憐的情緒,唯有時刻保持清醒,才能看清

Assistance Required HDU - 1216 (模擬+連結串列)

題目 複習一些, 對於常用刪除和插入操作的資料結構要用list, 對於遍歷和查詢更多的資料結構要用集合, 這道題很顯然要用list #include <cstdio> #include <iostream> #include <algorithm>

HDU 6058 列舉 Kanade's sum

題目 Kanade's sum Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 2496    Accept

HDU 4286 Data Handler (雙向連結串列

                                                 Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) P

2017多校聯合第八場/hdu 6136Death Podracing(優先佇列+迴圈連結串列

> During the Trade Federation invasion of Naboo, Anakin Skywalker won the Boonta Eve Classic on Tatooine, securing his freedom from a life of slavery.

hdu 6058 Kanade's sum(鏈表)

php blank pri 暴力 splay href .cn 每次 n) 題目鏈接:hdu 6058 Kanade‘s sum 題意: 給你一個n個數的排列,問你全部區間第k大的總和為多少。 題解: 我們只要求出對於一個數x左邊最近的k個比他大的和右邊最近k個比他大的,掃

hdu-6058 Kanade's sum

con sta cst getchar urn bsp pen define set   題意:略   思路:要我們求每個區間第K大數之和,其實可以轉換為求多少個區間的第K大數是X,然後我們在求和就好了。      那麽我們可以從小到大枚舉所有可能成為第K大的數。為什麽從小

【鏈表】2017多校訓練3 HDU 6058 Kanade's sum

iostream ++ 多校 open pos cnblogs names mat play acm.hdu.edu.cn/showproblem.php?pid=6058 【題意】 給定一個排列,計算 【思路】 計算排列A中每個數的貢獻,即對於每個ai,計算有

hdu 6058 To my boyfriend (計算貢獻,思維)

時間 () light 區間 frame enc const log -- 題意: 給你一個全排列,要你求這個序列的所有區間的第k大的和 思路:比賽的時候一看就知道肯定是算貢獻,也知道是枚舉每個數,然後看他在多少個區間是第K大,然後計算他的貢獻就可以了,但是沒有找到如何在o

hdu 6058 思維

return 例子 cstring sca 計算 ase 雙鏈表 += code 題目:http://acm.hdu.edu.cn/showproblem.php?pid=6058 分析題目的時候,由於枚舉的區間很多,而第k大的值範圍小,應該要想到去枚舉第k大的值然後找到這

HDU 6058

鏈表 font 維護 nbsp col != turn ret 代碼 題意略。 思路:這題要求第k大之和,我們可以算每個數字對答案的貢獻。這次,我們采取一個特殊的手法:我們按數字的大小,從小到大來計算貢獻。 先從1開始計算,我們知道,1周圍的數字都比1大,假設1在位置p,那

c實現功能(13)實現單向連結串列的簡要功能

#include <stdio.h> #include <stdlib.h> //利用結構體建立節點 struct list{ //建立資料域 int data; //建立指標域 struct list *next; }; //實現建立一個

LeetCode 25. k個一組翻轉連結串列(Reverse Nodes in k-Group)

題目描述   給出一個連結串列,每 k 個節點一組進行翻轉,並返回翻轉後的連結串列。 k 是一個正整數,它的值小於或等於連結串列的長度。如果節點總數不是 k 的整數倍,那麼將最後剩餘節點保持原有順序。 示例 : 給定這個連結串列:1->

連結串列劃分為左小、中相等、右大

解題思路:將一個連結串列分成三個連結串列,最後重新連線三個連結串列 (1)分成三個連結串列的過程是一致的:以左小連結串列為例 依次遍歷原連結串列的每一個節點cur,當cur->data<pivot時,把cur取出, 新增到左小連結串列末尾,直到遍歷完整個原連結串列為止

往有序單迴圈連結串列的插入元素使原連結串列依舊有序

解題思路:與有序單鏈表類似,只不過加了尾指標指向連結串列頭部 #include<iostream> using namespace std; typedef struct TNode { int data; struct TNode* next; }TN

往有序連結串列的插入元素使原連結串列依舊有序

/* 在有序連結串列中插入元素時,最好設定兩個指標,一前一後, cur指標負責比較大小,pre指標負責定位插入位置的前驅。 【關鍵點】 (1)3中情況:空連結串列、第一個值比插入元素大、非空連結串列&&第一個元素比插入元素小 (2)pre、cur指標的初始值